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

Angular 在这种情况下,如何设置默认表单控件值?,angular,angular-reactive-forms,controlvalueaccessor,Angular,Angular Reactive Forms,Controlvalueaccessor,我目前正在使用自定义表单字段控件开发可重用组件 我有一个自定义的自动完成控件,它返回一个对象作为它的值,然后我的可重用组件使用这个自定义控件,将一个对象属性作为字符串传递给我的主窗体。这里有一个闪电战来检查它: 这在一个方向上可以正常工作,即控制-->可重用字段-->表单 以下是我如何从可重用组件更新表单值: ngOnInit(){ this.state = new FormControl(null); // any time the form field va

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

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

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

以下是我如何从可重用组件更新表单值:

  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();
                }
      });
  }
现在,当我将默认值设置为ReusableComponent字段时,控件被正确更新,但表单值没有被正确更新。我尝试调用
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);
}

但这也不行。
我错过了什么?有什么线索吗?

有几件事

  • 表单组的默认值将覆盖表单提供的值,在
    ngOnInit
    钩子的末尾调用
    writeValue
    方法。您可以通过在稍后的钩子中以可重用的形式调用
    setValue
    来解决这个问题

  • 在blitz中,您正在应用程序组件中使用onPush更改检测。这意味着只有某些事情会触发更改检测,更新被动表单值的子组件不在其中。这就是为什么您看不到模板中反映的更改。如果您只对表单值感兴趣而不想在屏幕上显示它,那么这并不是什么大不了的事,但是如果您想显示它,那么这是一件大不了的事,就像您删除onPush更改检测一样,您将开始看到表达式更改错误,作为子级,在初始化期间更新父模板中的内容会违反单向数据流。解决这个问题有点困难。这里真正的答案是,您的父窗体确实应该是提供默认值的窗体


  • 要快速解决问题,请添加

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

    在可重用表单字段中的
    ngOnInit
    结尾处。

    在一个级别上混合ngModel和在另一个级别上混合反应表单似乎是一个奇怪的选择。为什么不一路走下去呢?嗯,我不知道我是否有一个好的答案。我遵循angular material的指导。这就是它所暗示的,它是有效的,所以我保留了它…我知道变化检测在这里是个问题。我的计划B是在我的主窗体上设置默认值,尽管我应该使用整个对象来传递正确的值。我曾尝试在稍后的钩子(ngAfterViewInit)上设置值,但这不起作用,直到我使用了上面答案中的
    setTimeout
    解决方法…超时会触发更改检测,我通常会在实践中尝试避免,但我知道。。。除了在主窗体上设置值之外,我想不出其他任何东西,但接下来我必须处理两个控件,一个是用对象更新可重用组件,另一个是接受字符串的实际窗体控件……它在AfterViewInit钩子上工作,而不是在NgOnit上。谢谢