问题
在模板中显示相应的元素后获得@ViewChild的最优雅的方式是什么?
下面是一个例子。也可提供活塞。
Component.template.html:
<div id="layout" *ngIf="display">
<div #contentPlaceholder></div>
</div>
Component.component.ts:
export class AppComponent {
display = false;
@ViewChild('contentPlaceholder', { read: ViewContainerRef }) viewContainerRef;
show() {
this.display = true;
console.log(this.viewContainerRef); // undefined
setTimeout(() => {
console.log(this.viewContainerRef); // OK
}, 1);
}
}
我有一个默认隐藏其内容的组件。当有人调用show()方法时,它变得可见。然而,在Angular 2变更检测完成之前,我不能引用viewContainerRef。如上所示,我通常将所有必需的操作包装到setTimeout(()=>{},1)中。有没有更正确的方法?
我知道ngAfterViewChecked有一个选项,但它会导致太多无用的调用。
答案(设置)
我自己在使用Angular 10时也遇到了同样的问题。
如果我尝试使用[hidden]或*ngIf,那么@ViewChild变量总是未定义的。
<p-calendar #calendar *ngIf="bShowCalendar" >
</p-calendar>
我没有把它从网页上删除。
我使用了一个[ngClass]使控件的透明度为:0,并将它完全移开。
<style>
.notVisible {
opacity: 0;
left: -1000px;
position: absolute !important;
}
</style>
<p-calendar #calendar [ngClass]="{'notVisible': bShowCalendar }" >
</p-calendar>
我知道,这很蠢很丑,但它解决了问题。
我还必须让控制变成静态的。我不明白为什么…但是,再一次,它拒绝在没有改变的情况下工作:
export class DatePickerCellRenderer {
@ViewChild('calendar', {static: true }) calendar: Calendar;
为ViewChild使用setter:
private contentPlaceholder: ElementRef;
@ViewChild('contentPlaceholder') set content(content: ElementRef) {
if(content) { // initially setter gets called with undefined
this.contentPlaceholder = content;
}
}
一旦*ngIf变成true, setter就会被元素引用调用。
注意,对于Angular 8,你必须确保设置{static: false},这是其他Angular版本的默认设置:
@ViewChild('contentPlaceholder', { static: false })
注意:如果contentPlaceholder是一个组件,你可以改变ElementRef到你的组件类:
private contentPlaceholder: MyCustomComponent;
@ViewChild('contentPlaceholder') set content(content: MyCustomComponent) {
if(content) { // initially setter gets called with undefined
this.contentPlaceholder = content;
}
}