0

我目前正在使用自定义表单字段控件开发可重用组件。

我有这个自定义的自动完成控件,它返回一个对象作为它的值,然后我的可重用组件使用这个自定义控件将对象属性之一作为字符串传递给我的主窗体。这是一个闪电战来检查它:

https://stackblitz.com/edit/my-custom-autocomplete-jlkj9q

这在一个方向上工作正常,控制-> 可重用字段-> 表单。

以下是我从可重用组件更新表单值的方法:

  ngOnInit(){

      this.state = new FormControl(null);

      // any time the form field value changes update the parent of any change
      this.state.valueChanges
              .pipe(takeUntil(this._destroy))
              .subscribe(value => {
                if(!!value && !!value.name){
                  this.onChange(value.name) //pass only the state.name to the ControlValueAccessor
                  this.onTouched();
                }
                else{
                  this.onChange(value)
                  this.onTouched();
                }
      });
  }

现在,当我为可重用组件字段设置默认值时,控件会正确更新,但表单值不会。我尝试使用要传递给主窗体的值调用该onChange()方法,但什么也没发生。ngOnInit然后我尝试在 ngAfterViewInit 上设置默认值并onChange像这样调用:

ngAfterViewInit(){

      let defaultValue = {
                  "name": "Arkansas",
                  "population": "2.978M",
                  "flag": "https://upload.wikimedia.org/wikipedia/commons/9/9d/Flag_of_Arkansas.svg"
                };

      this.state.setValue(defaultValue);    
      this.onChange(defaultValue);
}

但这也不起作用。
我在这里想念什么?有什么线索吗?

4

2 回答 2

1

为了快速解决方法添加

setTimeout(() => this.state.setValue(this.defaultValue), 0);

ngOnInit在可重复使用的表单字段的末尾。

于 2020-02-08T15:55:49.047 回答
0

几件事...

  1. 您的表单组的默认值覆盖您的表单提供的默认值,该方法在钩子writeValue结束时调用。ngOnInit您可以通过简单地setValue在以后的钩子中调用可重用的表单来解决这个问题

  2. 您正在闪电战中的应用组件中使用 onPush 更改检测。这意味着只有某些事情会触发更改检测,并且更新响应式表单值的子组件不是其中之一。这就是为什么您没有看到更改反映在模板中的原因。如果您只对表单值感兴趣而不是在屏幕上显示它,这没什么大不了的,但是如果您想显示它,这很重要,就像您删除 onPush 更改检测一样,您将开始看到表达式更改错误,因为在初始化期间更新父模板中的某些内容的子违反了单向数据流。绕过这个有点困难。真正的答案是您的父表单确实应该是提供默认值的表单。

于 2020-02-08T15:52:19.873 回答