接受的答案增加了对苍蝇的很大依赖性。模态(和非模态)对话框很大程度上是一两个 CSS 类的结果。试试这个“重命名...”示例:
1) 编写父模式和子模式,就好像子模式根本不是模式一样,而只是一个附有 *ngIf 的内联表单。
使用<my-modal>child 的父 HTML:
<div>
A div for {{name}}.
<button type="button" (click)="showModal()">Rename</button>
<my-modal *ngIf="showIt" [oldname]="name" (close)="closeModal($event)"></my-modal>
</div>
父类。为简洁起见,省略了 @Component 装饰器。 (name 属性属于父类,即使我们没有表单来更改它也会存在。)
export class AppComponent {
name = "old name";
showIt = false;
showModal() {
this.showIt = true;
}
closeModal(newName: string) {
this.showIt = false;
if (newName) this.name = newName;
}
}
子成为模态组件。 @Component 装饰器和导入再次省略。
export class MyModalComponent {
@Input() oldname = "";
@Output() close = new EventEmitter<string>();
newname = "";
ngOnInit() {
// copy all inputs to avoid polluting them
this.newname = this.oldname;
}
ok() {
this.close.emit(this.newname);
}
cancel() {
this.close.emit(null);
}
}
模态化之前的子 HTML。
<div>
Rename {{oldname}}
<input type="text" (change)="newname = $event.target.value;" />
<button type="button" (click)="ok()">OK</button>
<button type="button" (click)="cancel()">Cancel</button>
</div>
2) 这是子级的 CSS,但它可以放在全局样式表中,以便在整个应用程序中重复使用。它是一个名为modal 的单一类,用于<div> 元素。
.modal {
/* detach from rest of the document */
position: fixed;
/* center */
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
/* ensure in front of rest of page -- increase as needed */
z-index: 1001;
/* visual illusion of being in front -- alter to taste */
box-shadow: rgba(0,0,0,0.4) 10px 10px 4px;
/* visual illusion of being a solid object -- alter to taste */
background-color: lightblue;
border: 5px solid darkblue;
/* visual preference of don't crowd the contents -- alter to taste */
padding: 10px;
}
但是modal CSS 类不会阻止与它下面的页面交互。 (所以它在技术上创建了一个无模式对话框。)所以我们在模式下方放置一个overlay 来吸收和忽略鼠标活动。 overlay 也适用于 <div> 元素。
.overlay {
/* detach from document */
position: fixed;
/* ensure in front of rest of page except modal */
z-index: 1000;
/* fill screen to catch mice */
top: 0;
left: 0;
width: 9999px;
height: 9999px;
/* dim screen 20% -- alter to taste */
opacity: 0.2;
background-color: black;
}
3) 在子 HTML 中使用 modal 和 overlay。
<div class="modal">
Rename {{oldname}}
<input type="text" (change)="newname = $event.target.value;" />
<button type="button" (click)="ok()">OK</button>
<button type="button" (click)="cancel()">Cancel</button>
</div>
<div class="overlay"></div>
就是这样。基本上 2 个 CSS 类,您可以使任何组件成为模态。事实上,您可以在运行时将组件显示为内联或模式,只需使用 ngClass 或 [class.modal]="showAsModalBoolean" 更改 CSS 类的存在即可。
您可以更改此设置,以便孩子控制显示/隐藏逻辑。将 *ngIf、showIt 和 show() 函数移到子项中。在父级中添加@ViewChild(MyModalComponent) renameModal: MyModalComponent;,然后父级可以强制调用this.renameModal.show(this.name); 并根据需要重新连接初始化并包含div。
child-modal 可以将信息返回给父函数,如上所示,或者子函数的 show() 方法可以接受回调或返回 Promise,根据口味。
要知道的两件事:
如果<my-modal> 上有*ngIf,this.renameModal.show(..); 将不起作用,因为它不存在以公开函数开始。 *ngIf 会删除整个组件、show() 函数和所有组件,因此如果出于某种原因需要,请改用 [hidden]。
Modals-on-modals 会有 z-index 问题,因为它们都共享相同的 z-index。这可以通过[style.z-index]="calculatedValue" 或类似方式解决。