驰名的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(); });
总结
排错的路千万条,翻译、瞎猜第一条。