驰名的select2终于有热心的大牛构建了angular版本,并命名为ng-select2。但(猜测)因为其外围的代码依赖于jquery,所以在联合formControl应用时,会产生如下异样:Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value for 'ng-pristine': 'true'. Current value: 'false'.

情景再现

比方咱们有以下组件树:

一个一般的A组件,一个能够实现了ControlValueAccessor接口并申明为FormControl的B组件,一个援用的ng-select2组件。

其中A组件蕴含B组件、B组件又蕴含ng-select2组件。

ng-select2组件中的数据列表是通过资源申请失去的列表,所以是异步数据,B组件V层示例如下:

<ng-select2  [value]="datum"  [data]="data"  (valueChanged)="onChanged($event)"</ng-select2>

B获取select2应用的数据列表data示例代码如下:

ngOnInit(): void {    this.service.getAll()        .subscribe(data => {            // 在这设置ng-select2的数据列表            this.data = data;        });}

此时在A组件将会产生如下谬误:Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value for 'ng-pristine': 'true'. Current value: 'false'.

起因猜测

咱们晓得,因为在大牛们会具体的解释异样产生的起因,所以解决问题的第一步也是最重要的一步便是翻译:
严重错误:表达式被检测结束当前却产生了变更谬误:当表达式被检测结束当前却又产生了变更。检测结束时,检测的'ng-pristine'的值为'true'. 以后值为:'false'
同时pristine可译为原始的

所以我猜错主大略是如下产生的:

也就是说:将A组件在渲染结束的状况下,发现FormControl的值产生了变动,则会产生ExpressionChangedAfterItHasBeenCheckedError异样。

解决办法

ng-select2的官网demo中给出了当列表值异步时的解决方案,但遗憾的是该办法同样会引发上述异样。

该异样产生的次要起因是因为A组件处于渲染结束,使得A中做为FormControl的组件B同样处于tHasBeenChecked状态,所以解决该问题也能够如下着手:

如上图所示,当组件B在接管到异步数据时,为了避免其子组件ng-select2进行数据弹射时A组件处于渲染结束状态,咱们在此手动的触发从新渲染所有组件的办法。此时将A组件接管到最新的值时,其状态处于渲染中,当然也就不会呈现HasBeenChecked异样了。

代码如下:

constructor(private service: Service,  private changeDetectorRef: ChangeDetectorRef) {}ngOnInit(): void {    this.service.getAll()        .subscribe(data => {            // 在这设置ng-select2的数据列表            this.data = data;            // 手动调用组件渲染办法,从新渲染各组件            this.changeDetectorRef.detectChanges();        });

总结

排错的路千万条,翻译、瞎猜第一条。