简体   繁体   English

Angular2,应用程序内所有其他组件的通用覆盖组件

[英]Angular2, generic overlay component for all other components inside the app

I have the following two components: 我有以下两个组成部分:

overlay 覆盖

@Component({
    selector: 'overlay',
    template: '<div class="check"><ng-content></ng-content></div>'
})
export class Overlay {
    save(params) {
        //bunch of stuff that are commonly used
    }
}

myComponent (there are many more like this) myComponent(还有很多这样的)

@Component({
    selector: 'myComponent',
    directives: [Overlay],
    template: '<overlay><form (ngSubmit)="save({ name: 'sam', lastName: 'jones' })">I'm the component. Click <input type="submit">Here</input> to save me!</form></overlay>'
})
export class MyComponent {

}

This solutions doesn't work with no errors thrown, Angular2 simply skips both components initialization. 没有抛出错误,这个解决方案不起作用,Angular2只是跳过两个组件初始化。 Anyways, i think you get the idea here. 无论如何,我想你在这里得到了这个想法。 There's a common component which will need to wrap a lot of other components hence it needs to be generic. 有一个共同的组件需要包装许多其他组件,因此它需要是通用的。 It has a template so services don't do the job. 它有一个template所以服务不能完成这项工作。 I haven't worked much with custom annotations, maybe they could do something like this? 我没有使用自定义注释,也许他们可以做这样的事情? Any thoughts on how to achieve such a functionality? 有关如何实现这种功能的任何想法?

note: the overlay contains logic and template, both of which are needed for any other component that needs to use it. 注意:叠加层包含逻辑和模板,这些都是需要使用它的任何其他组件所需要的。 The template is a complex modal dialog with animations, messages, fades etc... that is common across the solution. 模板是一个复杂的模态对话框,包含动画,消息,淡入淡出等......这在整个解决方案中很常见。

Update 更新

Found this: Angular2: progress/loading overlay directive 发现这个: Angular2:progress / loading overlay指令

Ok maybe this is not a direct answer to your question, but from your comment I guess you want to implement modals inside your app. 好吧也许这不是你的问题的直接答案,但从你的评论我想你想在你的应用程序中实现模态。 I haven't done it yet but in near future I will (this is part of my app's requirement). 我还没有完成它 ,但在不久的将来我会(这是我应用程序要求的一部分)。

First I do not use bootstrap javascript because I'm using angular already. 首先我不使用bootstrap javascript,因为我已经使用了角度。 The only thing that you need is bootstrap css . 你唯一需要的是bootstrap css

consider below root template: 考虑以下根模板:

 <my-app></my-app>

 <my-modal>
    <div class="modal-container">
       <div class="modal-content">{{modalContent}}</div>
    </div>
 </my-modal>

show your modal: Global Event 展示你的模态:全球事件

You can show your modal from any component . 您可以从任何component显示模态。 The trick is to inject a modal-service to send a global event . 诀窍是注入modal-service来发送全局事件 see this answer to see how it works. 看到这个答案,看看它是如何工作的。

You can send any object as event . 您可以将任何对象作为event发送。 This event object could contains your modal's contents or a key so modal component can fetch it from some where else. 此事件对象可能包含模态的内容或key因此模态component可以从其他位置获取它。

ModalComponent ModalComponent

Your ModalComponent should subscribe to that event. 您的ModalComponent应订阅该事件。 On event you can show and hide it (the modal component) in several ways that i'm sure your are aware of. 在事件中,您可以通过几种方式显示和隐藏它(模态组件),我确信您已经知道。 Using structural directives is one way. 使用结构指令是一种方法。

Style 样式

A modal is a container ( .modal-container ) with width and height of viewport with transparent background. 模态是一个容器( .modal-container ),具有透明背景的视口 widthheight Modal's content ( .modal-content ) is another container with fixed width and height and absolute position. Modal的内容( .modal-content )是另一个具有固定widthheight以及absolute位置的容器。 If you want bootstrap styles you can add it and for animations you can use angular animations 如果您想要自举样式,可以添加它,对于动画,您可以使用角度动画

I'm currently using a similar approach for menubar and it works very well!! 我目前正在使用类似的方法进行菜单栏,它的效果非常好!!

I created one for this specific task and thought about embedding bootstrap modal as template but came across a couple of issues such as the fact that the only useful piece out of bootstrap modal would be the class names. 我为这个特定的任务创建了一个,并考虑将bootstrap模式嵌入作为模板,但遇到了一些问题,例如,bootstrap模式中唯一有用的部分是类名。 Not surprisingly, didn't want that for this specific task since I needed to distinguish between window modals and progress modals on components. 毫不奇怪,因为我需要区分窗口模态和组件上的进度模态,所以不希望这个特定的任务。

Overlay 覆盖

@Component({
    selector: 'overlay',
    template:
    `<div [ngClass]="isOpen ? 'opened' : 'closed'">
         <div class="modal" role="dialog">
            <div class="modalBody">
                <div *ngIf="isSaving">
                    <span class="text-success text-bold">
                        Saving...
                    </span>
                </div>
                <div *ngIf="isSaved">
                    <span class="text-success text-bold">
                        Saved.
                    </span>
                </div>
            </div>
        </div>
    </div>`,
    styles: [
        '.modal { position:absolute; width: 100%; height: 100%; margin: -30px; background-color: rgba(255, 255, 255, 0.7); z-index: 1000; text-align: center; }',
        '.closed { visibility: hidden; }',
        '.opened { visibility: visible; }',
        '.modalBody { top: 45%; left: 25%; width: 50%; position: absolute; }',
        '.text-bold { font-weight: 800; font-size: 1.5em; }'
    ]
})
export class Overlay implements OnChanges, AfterContentInit {
    @Input() isSaving: boolean = false;
    @Input() isSaved: boolean = false;
    @Input() containerElement: HTMLElement;

    isOpen = false;

    private modalElement;

    constructor(private element: ElementRef, private animationBuilder: AnimationBuilder) { }

    ngOnChanges() {
        if (this.modalElement) {
            if (this.isSaving == true || this.isSaved == true) {
                this.toggleAnimation(true);
            }
            else if (this.isSaving == false && this.isSaved == false) {
                this.toggleAnimation(false);
            }
        }
    }

    ngAfterContentInit() {
        this.containerElement.style.position = 'relative';
        this.modalElement = this.element.nativeElement.querySelector('.modal');
    }

    private toggleAnimation(isOpen) {
        var startCss = { backgroundColor: 'rgba(255, 255, 255, 0)' };
        var endCss = { backgroundColor: 'rgba(255, 255, 255, 0.7)' };

        if (isOpen) {
            this.isOpen = true

            this.animation(
                true,
                this.modalElement,
                400,
                startCss,
                endCss,
                null
            );
        }
        else {
            this.animation(
                isOpen,
                this.modalElement,
                400,
                startCss,
                endCss,
                () => {
                    this.isOpen = false;
                }
            );
        }
    }

    private animation(isStart, element, duration, startCss, endCss, finishedCallback) {
        var animation = this.animationBuilder.css();

        animation.setDuration(duration);

        if (isStart) {
            animation.setFromStyles(startCss).setToStyles(endCss);
        } else {
            animation.setFromStyles(endCss).setToStyles(startCss)
        }

        animation.start(element);

        if (finishedCallback) {
            setTimeout(finishedCallback, duration);
        }
    }
}

Usage 用法

As is, you'll need a relative container in order for overlay to fill its parent. 因此,您需要一个相对容器才能使overlay填充其父级。 The css definitely needs modifications to accommodate for a few scenarios such as mobile devices and non-positioned containers. css肯定需要修改以适应一些场景,例如移动设备和非定位容器。 Here's how it's currently used: 以下是它目前的使用方式:

HTML HTML

<form action="/edit" method="post" #myForm="ngForm" (ngSubmit)="save ajax method that will update the isSaving and isSaved accordingly" novalidate>
    <div style="position: relative;" #overlayContainer>
        <overlay [isSaving]="isSaving" [isSaved]="isSaved" [containerElement]="overlayContainer"></overlay>
    </div>
</form>

After saving the form , an overlay is shown within the containerElement for 400ms and is faded out and goes hidden afterwards until the next save attempt. 保存form ,在containerElement显示一个overlay 400ms并逐渐淡出并在之后隐藏,直到下一次保存尝试。 The isSaving and isSaved binding values are the responsibility of the any component that wishes to use the overlay . isSavingisSaved绑定值是希望使用overlay的任何组件的责任。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM