我目前需要在一些地方执行以下操作,以确保对话框仅在打开时才出现在DOM中。
<vcd-modal *ngIf="modalOpen" [(open)]="modalOpen" ...>
我想为语法糖创建一个指令,该指令看起来像<vcd-modal *vcdModalOpen[modalOpen]>
,它为我处理了双重绑定。我有以下代码
import {AfterViewChecked, Directive, EmbeddedViewRef, Input, TemplateRef, ViewContainerRef} from "@angular/core";
@Directive({
selector: "vcd-modal[vcdModalOpen]"
})
export class ModalOpenDirective implements AfterViewChecked {
private hasView = false;
// Unsure how to get this, this is the component where
// `this.modalOpen` is defined
private parent: any;
constructor(
private modal: VcdModalComponent,
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef) {
}
@Input() set vcdModalOpen(condition: boolean) {
if (!condition && !this.hasView) {
this.viewContainer.clear();
this.hasView = false;
// Need to unsubscribe from previously created components
} else if (condition && this.hasView) {
this.viewContainer.createEmbeddedView(this.templateRef);
this.hasView = true;
// Bind one from modal to the parent
this.modal.openChange.subscribe((open) => {
this.parent.modalOpen = open;
});
// Bind from the parent to the modal
const oldNgOnChanges = this.parent.ngOnChanges;
this.parent.ngOnChanges = (changes: SimpleChanges) => {
oldNgOnChanges.call(this, changes);
this.model.open = this.parentModalOpen;
}
}
}
}
由于以下原因,它不起作用:
modalOpen
标志modalOpen
状态的属性名称可以是任何东西,不一定是modalOpen
,但表达式已由Angular求值我认为我可以将父项和属性名称作为字符串传递,但是我将失去类型安全性,最终将需要比带有*ngIf
和双重绑定的示例更多的代码。 / p>
有没有一种方法可以实现我正在寻找的语法糖?
答案 0 :(得分:0)
您将指令传递给主题。当指令接收到主题时,对话框将打开,而当对话框关闭时,指令将发出结果。
component.ts
@Component({})
export class MyComponent {
public modalOpen$: Subject<Subject<any>> = new Subject();
public function open() {
const s = new Subject();
s.subscribe(result => {
console.log('dialog result', result);
});
this.modalOpen$.next(s);
}
}
component.html
<vcd-modal *ngIf="modalOpen$ | async">
现在您更改指令以使用该主题。
@Directive({...})
export class ModalOpenDirective implements AfterViewChecked {
private hasView = false;
constructor(
private modal: VcdModalComponent,
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef) {
}
@Input() set vcdModalOpen(parent: Subject<any>) {
if (!parent && !this.hasView) {
this.viewContainer.clear();
this.hasView = false;
} else if (parent && this.hasView) {
this.viewContainer.createEmbeddedView(this.templateRef);
this.hasView = true;
this.modal.openChange.subscribe((open) => {
// ^^ I'm not sure what this is but emit it back to the parent
parent.next(open);
});
}
}
}
以上内容基于主题对象为 truthy 的想法进行工作,并将显示模板。当指令发出结果时,父组件然后可以发出undefined
作为下一个删除模板的值。