这个问题的答案在于 angular(6) 属性,它适用于 shadow DOM 并且只监听 angular zone 内发生的变化,当像 TogetherJS 这样的第三方库更新 DOM 时,相应的变化不会影响角度组件,因为它们不是订阅实际的 DOM 原生元素。

为了解决这个问题,我们做了以下工作:
- 在 Form 类构造函数中注册一个回调以捕获从 Co-Browsing 库触发的 DOM“<strong>change”事件,即发生在 angular zone 之外,如下所述:
代码片段
constructor(private formBuilder: FormBuilder,private elementRef: ElementRef,private _renderer: Renderer,private cdr:ChangeDetectorRef,private app:ApplicationRef,private zone:NgZone) {
zone.runOutsideAngular(() =>{
window.document.addEventListener('change', this.change.bind(this));
})
}
- 定义 eventHandler 以执行以下操作:
- 使用 this.zone.run() 在 Angular 上下文中运行
- 使用 ElementRef 获取组件的模板选择器。
- 在输入元素上运行 queryselector 并与事件的 outerHTML 进行比较,以检查组件中哪个元素发生了变化。
- 为匹配元素设置 Formcontrol 的值。
PS:这里 customerForm 是 ControlValueAccesor FormGroup 类型的实例。在您的情况下,它可以是您的表格。我们可以概括表单(如果反应式)键遍历,如另一个 SO 帖子
Angular 2:迭代反应式表单控件中所述
代码片段:
change(event){
event.preventDefault();
console.log("DOM value changed" ,event);
console.log("component value", this.elementRef.nativeElement);
this.zone.run(() => { console.log('Do change detection here');
//this.cdr.detectChanges();
if(this.elementRef.nativeElement.querySelectorAll('input')[0].outerHTML === event.target.outerHTML)
{
console.log('Inside value updation');
//this.customerForm.controls.name.value=event.target.value;
this.customerForm.controls['name'].setValue(event.target.value);
}
});
setTimeout(() =>{
this.cdr.markForCheck();
})
}
这将设置组件中更改的元素的相应值(显然是通过遍历循环),并且验证不应该失败,因为它发生在当前上下文中。
以上细节的核心思想是如何捕获发生在角度区域之外的变化事件并相应地更新角度应用程序。
PS:我将更新github中的完整代码以供其他人阅读。