在这种情况下如何设置默认的表单控件值?

How do I set the default form control value in this situation?

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

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

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();
                }
      });
  }

现在,当我为可重用组件字段设置默认值时,控件会正确更新,但表单值不会。我尝试使用要传递给主窗体的值调用 ngOnInit 上的 onChange() 方法,但没有任何反应。然后我尝试在 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);
}

但这也不起作用。
我在这里错过了什么?有什么线索吗?

几件事...

  1. 您的表单组的默认值覆盖了您的表单提供的值,writeValue 方法在 ngOnInit 挂钩的末尾被调用。您可以通过在稍后的钩子

  2. 中以可重复使用的形式简单地调用 setValue 来解决这个问题
  3. 您在 blitz 中的应用程序组件中使用了 onPush 更改检测。这意味着只有某些事情会触发变更检测,而更新反应式表单值的子组件不是其中之一。这就是为什么您没有看到更改反映在您的模板中的原因。如果你只对表单值感兴趣而不是在屏幕上显示它,这没什么大不了的,但如果你想显示它,这就很重要了,就像你删除 onPush 变化检测一样,你会开始看到表达式更改错误,因为子项在初始化期间更新父项模板中的某些内容违反了单向数据流。解决这个问题有点困难。这里真正的答案是您的父表单确实应该是提供默认值的表单。

如需快速解决方法,请添加

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

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