typescript Angular2,应用程序内所有其他组件的通用覆盖组件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37951516/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular2, generic overlay component for all other components inside the app
提问by RoninCoder
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. 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. I haven't worked much with custom annotations, maybe they could do something like this? Any thoughts on how to achieve such a functionality?
这个解决方案在没有抛出错误的情况下不起作用,Angular2 只是跳过了两个组件的初始化。无论如何,我想你明白了。有一个通用组件需要包装许多其他组件,因此它需要是通用的。它有一个template
因此服务无法完成的工作。我对自定义注释的工作不多,也许他们可以做这样的事情?关于如何实现这样的功能的任何想法?
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:进度/加载覆盖指令
采纳答案by RoninCoder
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. Not surprisingly, didn't want that for this specific task since I needed to distinguish between window modals and progress modals on components.
我为这个特定任务创建了一个,并考虑将 bootstrap modal 作为模板嵌入,但遇到了几个问题,例如 bootstrap modal 中唯一有用的部分是类名。毫不奇怪,对于这个特定的任务,我不想这样做,因为我需要区分组件上的窗口模式和进度模式。
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. The css definitely needs modifications to accommodate for a few scenarios such as mobile devices and non-positioned containers. Here's how it's currently used:
按原样,您需要一个相对容器overlay
来填充其父容器。css 肯定需要修改以适应一些场景,例如移动设备和非定位容器。以下是它目前的使用方式:
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. The isSaving
and isSaved
binding values are the responsibility of the any component that wishes to use the overlay
.
保存后form
, anoverlay
会在containerElement
400 毫秒内显示,然后淡出并隐藏,直到下一次保存尝试。在isSaving
和isSaved
绑定值是任何组件的希望使用的责任overlay
。
回答by Seyed Jalal Hosseini
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 ityet but in near future I will (this is part of my app's requirement).
好吧,也许这不是对您问题的直接回答,但从您的评论中我猜您想在您的应用程序中实现模态。我还没有这样做,但在不久的将来我会这样做(这是我的应用程序要求的一部分)。
First I do not use bootstrap javascriptbecause I'm using angular already. The only thing that you need is bootstrap css.
首先,我不使用 bootstrap javascript,因为我已经在使用 angular。您唯一需要的是 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
. The trick is to inject a modal-service
to send a global event. see thisanswer to see how it works.
您可以从任何component
. 诀窍是注入一个modal-service
来发送一个全局事件。请参阅此答案以了解其工作原理。
You can send any object as event
. This event object could contains your modal's contents or a key
so modal component
can fetch it from some where else.
您可以将任何对象作为event
. 这个事件对象可以包含你的模态的内容,或者一个key
模态component
可以从其他地方获取它。
ModalComponent
模态组件
Your ModalComponent
should subscribe to that event. On event you can show and hide it (the modal component) in several ways that i'm sure your are aware of. Using structural directivesis one way.
您ModalComponent
应该订阅该事件。在事件中,您可以通过我确定您知道的几种方式来显示和隐藏它(模态组件)。使用结构指令是一种方法。
Style
风格
A modal is a container (.modal-container
) with width
and height
of viewportwith transparent background. Modal's content (.modal-content
) is another container with fixed width
and height
and absolute
position. If you want bootstrap styles you can add it and for animations you can use angular animations
模态是一个容器(.modal-container
)与width
和height
的视口与透明背景。模态的内容(.modal-content
)是具有固定的另一个容器width
并height
和absolute
位置。如果你想要引导样式,你可以添加它,对于动画,你可以使用角度动画
I'm currently using a similar approach for menubar and it works very well!!
我目前正在对菜单栏使用类似的方法,并且效果很好!!