angular - 带表单组的子 ControlValueAccessor 组件 - 表达式在检查后已更改

标签 angular

在加载我的 组件时,我正在使用 patchValue 更新该(父)组件的形式。

在那个表单组件中,我的子 ControlValueAccessor 组件也有一个表单组。因此,在我的 writeValue 函数中,我正在根据从父组件 patchValue 传递的值更新子组件。

我的 writeValue 函数看起来像这样:

    writeValue(value: CountryAndCity): void {
    if (value != null && value.country && value.city) {
      this.isDefaultValueDefined = true;
      this.form.patchValue({country: value.country});
      this.form.patchValue({city: value.city});
      **this.cdRef.detectChanges();**
    }
  }

如您所见,我必须使用 detectChanges() 作为上述函数的最后一行,因为没有它我会收到错误消息:

ParentComponent.html:1 错误错误:ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后已更改。以前的值:'ng-pristine:true'。当前值:'ng-pristine: false'。

我想我明白为什么会这样。 Angular 开始检查父组件,然后开始检查子组件,然后,在子组件上,在子组件上,在 writeValue 函数上更改父组件的表单状态。

我对使用 detectChanges() 感到不舒服。有没有办法做其他事情?使用父组件和子组件时是否必须每个组件都有 formGroup 并且子组件是父 formgroup formControl 之一?

最佳答案

我不认为,这是因为您的 write 函数而发生的,而是您的表单中的某些东西在创建子项后立即发出值,但如果没有就很难判断查看更多您的代码。

我遇到了同样的问题,所以我在不手动触发更改检测的情况下为防止此错误所做的工作是将值传播到父级与当前更改检测周期分离。

实现这一点的一个简单方法是yield upstream 的值

this.form
  .valueChanges
  .pipe(
    delay(0)
  )
  .subscribe(it => {
    this.propagateChange(...)
  })

我不知道这是否是最好的方法,但对我来说它有效。

顺便说一句:我还建议使用 {emitEvent: false} 作为补丁选项,这样可以防止 child 在 write 函数中触发事件。如果您对错误来源的假设是正确的,这将解决您的问题,但如果我的假设是正确的,则不会。

关于angular - 带表单组的子 ControlValueAccessor 组件 - 表达式在检查后已更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48923588/

相关文章:

javascript - Angular 2 中的 CanActivate 返回未定义

angular - 如何像 Angular 2 中的 React 的 this.props.children 一样获取子组件?

angular - 升级@ngrx/Store 时,类型 'payload' 上不存在属性 'Action'

angular - Electron + Angular7 如何在组件中使用 serialport.list()

javascript - 如何解决 Angular 内存泄漏

javascript - Angular:呈现服务器端验证消息的正确方法

angular - 垫步显示所有步骤

javascript - 对象的类型为 'unknown'

angular - 如何在 Angular Material Grid 中设置行距?

javascript - 日期选择器:无法绑定(bind)到 'bsValue',因为它不是 'input' 的已知属性