首页 > 解决方案 > elementRef的宽度改变时如何改变模板

问题描述

我尝试在 ngInit 中加载一些数据并将 div 的宽度设置为等于接收到的数据。然后我尝试使用 ViewChild 和 ElementRef 在 ngAfterViewInit 中设置一些样式选项,但我的 elementRef 始终未定义。我该如何解决?

我的组件:

export class NewComponent implements OnInit, AfterViewInit {
    public data: number = 0;
    public showMe: bool = false;
    public redColor: bool = false;
    @ViewChild('myElement', { static: false}) myElement;

    constructor(private myService: MyService) {}

    public ngOnInit(): void {
        this.myService.loadData().subscribe(result => this.data = result);
    }

    public ngAfterViewInit(): void {
        console.log(this.myElement); // undefined
        console.log(this.myElement.nativeElement); // Cannot read property 'nativeElement' of undefined
        this.setStyleOptions(); 
    }

    public setStyleOptions() {
        if (this.myElement.nativeElement.clientWidth > 50) {
            this.showMe = true;
            this.redColor = true;
        }
        else {
            this.showMe = false;
            this.redColor = false;
        }
    }
}

我的模板:

<div *ngIf="some-condition">
    <div *ngIf="some-new-condition">
        <div #myElement [style.width.px]=data"></div>
        <div *ngIf="showMe" [class.red]="redColor">Text</div>
    </div>
</div>

我知道 elementRef 可能由于 *ngIf 指令而未定义,但我不能用 [hidden] 替换它,因为我将不得不替换所有外部 div 块中的指令。我也尝试使用 ViewChild setter,就像这里的 @ViewChild in *ngIf

private myElement: ElementRef;
@ViewChild('myElement', { static: false}) set content(content: ElementRef) {
    if (content) {
        this.myElement = content;
        this.setStyleOptions();
    }
}

但随后“Еxpression has changed after it was checked”出现在控制台中。设置超时也无济于事。

如何正确更改模板?

标签: angulartypescriptangular-lifecycle-hooks

解决方案


当您在某个条件下有“ViewChild”时,您需要“更改 Angular”来重新绘制。所以,一般来说你需要

condition=true;  //first makes the condition true
setTimeout(()=>{  //say Angular to "repaint" and then execute the function
  this.setStyleOptions()
})

您也可以使用changeDetectorRef。也就是说,你在构造函数中注入它

constructor (private cdr:ChangeDetectorRef){}

并使用

condition=true;  //first makes the condition true
this.cdr.markForCheck()     //say Angular to "repaint" 
this.setStyleOptions()  //then execute the function

推荐阅读