Angular - 自定义表单组件不反映父表单组值的直接值

Angular - Custom form component not reflect value immediate to parent form group value

面临来自自定义表单组件的价值传播问题。

如果在Jobtitle中写任何东西,它会直接反映从当前到顶级表格组。 同样的事情在自动添加输入的自定义组件中不起作用。而在feeMode中写入,则只在同一个formControl中体现。

但是,那么现在,如果开始写公司名称,那么所有的值都会更新到top form group

已创建如下 stackblitz

https://stackblitz.com/edit/angular-auto-add-input?file=src/app/app.component.html

请帮我看看我错过了什么。

反应式组

professional = this.fb.group({
    application: this.fb.group({
      jobTitle: ['', [Validators.required]],
      feeModel: this.fb.array([this.fb.control('', [Validators.required])], [Validators.required]),
      companyName: ['', [Validators.required]],
    })
  });

自定义组件:

 @Component({
  selector: 'shared-auto-add-input',
  templateUrl: './auto-add-input.component.html',
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => AutoAddInputComponent),
      multi: true
    }
  ]
})
export class AutoAddInputComponent implements OnInit, AfterViewInit {

  @Input() label: string;
  @Input() placeholder: string;
  @Input() max: number;
  @Input() formArrayName: string;
  @Input() errors: ErrorModel[];

  arrayControl: FormArray;
  form: FormGroup;

  constructor(
    @Optional() @Host() @SkipSelf()
    private controlContainer: ControlContainer,
    private fb: FormBuilder,
  ) { }

  ngOnInit() {
    if (!this.formArrayName) {
      throw new TypeError('\'formArrayName\' is required.');
    }
    this.form = this.fb.group({
      option: this.controlContainer.control.get(this.formArrayName)
    });
    this.arrayControl = this.form.get('option') as FormArray;
  }

  ngAfterViewInit() {
  }

  addOption() {
    this.arrayControl.push(this.fb.control('', this.controlContainer.control.get(this.formArrayName).validator));
  }

  removeOption(index: number) {
    this.arrayControl.removeAt(index);
  }

  stopNew(option, i) {
    return option.value === ''
      || i !== this.arrayControl.controls.length - 1
      || (this.max && this.arrayControl.controls.length === +this.max);
  }

  getErrors(error: FormControl) {
    let result = [];
    if (this.errors) {
      result = this.errors.filter((message) => {
        return error.hasError(message.key);
      });
    }
    return result;
  }
}

看起来您正在努力处理 HTML 文件上的数据绑定,因为您正在使用 json 过滤器绑定要在 HTML 上打印的完整对象。重新绘制 html 时似乎没有考虑更改,因为它必须比较对象内的数组。我不认为这是一个问题(取决于你想做什么)。

事实证明 angular 会进行更改检查,这取决于您如何绑定 HTML,在您的情况下是一个完整的对象,它不会深入检查它是否已更改。

值已更改但没有触发事件来重新呈现绝对父对象的值。在子组件中,您在 new form 下操作,仅引用原始 formControl 或 formarray。

this.fb({}) 创建一个新表单。控件值已更改,因为引用相同但随后无法呈现新值,因为没有来自父页面一直跟踪的父表单的触发器。

这就是为什么它总是传递给子项的表单组,这样您就不会在其中创建新的表单组。这样做,就可以很好地跟踪表单组。这是对您的代码的快速修改。我使用了 formcontrol,因为它更容易,但是你可以对 formArrays 使用相同的技巧。

https://stackblitz.com/edit/angular-xchddm

抱歉,我在自定义表单组件中更改值后错过了调用 updateValueAndValidity()

this.form.valueChanges
      .subscribe(() => {
        this.controlContainer.control.updateValueAndValidity();
      });

现在,它正在工作。

已解决 : https://stackblitz.com/edit/solved-angular-auto-add-input?file=src/app/auto-input/auto-add-input.component.ts