代码之家  ›  专栏  ›  技术社区  ›  Gaurav Srivastava

如果外部库修改了相应的dom本机元素值,则更新angular6 Form值

  •  0
  • Gaurav Srivastava  · 技术社区  · 6 年前

    我正在尝试用角6来协同划船表格.In共同浏览一个开源库togetherJS为远程方更新相应元素的DOM值索引.html(两行,一行在head,另一行在body)我观察到使用ControlValueAccessor Form type对应元素的DOM值是正在更新,但视图中的FormControl值未更新。 我的问题是如何将外部库对DOM元素所做的更改反映到视图中Angular6表单控件的元素值中。

    https://github.com/srigaurav1986/Angular-Forms.git

    如何复制:
    1.从上面的链接下载代码。
    2.使用“npm Install”安装依赖项
    3.运行“ng serve-o”
    4.在浏览器中打开“ http://localhost:4200/controlvalueaccessor
    5.点击“Start TogetherJs”
    6.在另一个浏览器窗口中复制弹出的链接。
    7.更新“名称”字段

    我们可以看到DOM字段值在远程端也得到了更新,但在按下“提交”按钮之后,我们可以看到FormControl值在远程端保持不变,但在另一端发生了变化。

    我尝试使用手动检测更改应用程序.tick,markforcheck()和detectchanges()API,但没有幸运。是吗有一种方法,在这种情况下,我们可以监听DOM元素更改上的某个事件并订阅它,还可以更新Formcontrol参数值。

    1 回复  |  直到 6 年前
        1
  •  0
  •   Gaurav Srivastava    6 年前

    这个问题的答案在于angular(6)属性,即它在shadow DOM上工作,并且只监听angular zone中发生的更改,当第三方库(如TogetherJS)更新DOM时,相应的更改不会影响angular组件,因为它们不订阅实际的DOM本机元素。

    enter image description here

    为了解决这个问题,我们做了以下工作:

    • 在窗体类构造函数中注册一个回调以捕获DOM 从共同浏览库触发的事件,即发生在角度区域之外,如下所述:

    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));
    
            })
        }
    
      • 在角度上下文中使用此区域运行()
      • 使用ElementRef获取组件模板选择器。
      • 对输入元素运行queryselector,并与outerHTML事件进行比较,以检查组件中哪个元素已更改。
      • 为匹配元素设置Formcontrols值。

    PS:这里customerForm是实例的ControlValueAccesor FormGroup类型。在你的情况下,它可以是你的形式。我们可以推广形式(如果是被动的)键遍历,如另一篇文章所述 Angular 2: Iterate over reactive form controls

    代码段:

      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中的完整代码以供其他人阅读。

    推荐文章