【问题标题】:Nested reactive form always valid嵌套的反应形式始终有效
【发布时间】:2018-12-15 09:54:13
【问题描述】:

我使用嵌套的响应式表单作为 FormControl。

这里是演示https://stackblitz.com/edit/angular-pmfq5z?file=app%2Fapp.component.ts

问题:即使嵌套无效,主表单也有效(尝试清除必填字段)。

如何通知主表单嵌套表单有效性更改?

主要表单组件:

import { Component, Input } from '@angular/core';
import { FormBuilder, FormGroup, ControlContainer, NgForm, Validators } from '@angular/forms';

@Component({
  selector: 'my-app',
  template: `
    <h1>Form</h1>
    <pre>Valid: {{ form.valid }}</pre>
    <form [formGroup]="form" (ngSubmit)="onSubmit(form.value)" novalidate>
      <label>name</label>
      <input formControlName="name">
      <app-address-form formControlName="address"></app-address-form>
      <button>submit</button>
    </form>
    <ng-container *ngIf="submitData">
      <span>submit data</span>
      <pre>{{ submitData }}</pre>
    </ng-container>
  `
})
export class AppComponent  {
  @Input() name: string;
  submitData = '';
  form: FormGroup;

  constructor(private fb: FormBuilder) {
    this.form = fb.group({
      name: fb.control('foo bar', Validators.required),
      address: fb.control({
        city: 'baz',
        town: 'qux',
      })
    });
  }

  onSubmit(v: any) {
    this.submitData = JSON.stringify(v, null, 2);
  }
}

嵌套表单组件:

import { Component, forwardRef } from '@angular/core';
import { ControlContainer, ControlValueAccessor, FormGroup, FormControl, NG_VALUE_ACCESSOR, NgControl, NgForm, Validators } from '@angular/forms';

// https://docs.google.com/presentation/d/e/2PACX-1vTS20UdnMGqA3ecrv7ww_7CDKQM8VgdH2tbHl94aXgEsYQ2cyjq62ydU3e3ZF_BaQ64kMyQa0INe2oI/pub?slide=id.g293d7d2b9d_1_1532
@Component({
  selector: 'app-address-form',
  template: `
    <div [formGroup]="form">
      <label>city</label>
      <input formControlName="city" (blur)="onTouched()">
      <label>town</label>
      <input formControlName="town" (blur)="onTouched()">
    </div>
  `,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      multi: true,
      useExisting: forwardRef(() => AddressFormComponent)
    }
  ]
})
export class AddressFormComponent implements ControlValueAccessor {
  form: FormGroup = new FormGroup({
    city: new FormControl('', Validators.required),
    town: new FormControl('', Validators.required)
  });

  onTouched: () => void = () => {};

  writeValue(v: any) {
    this.form.setValue(v, { emitEvent: false });
  }

  registerOnChange(fn: (v: any) => void) {
    this.form.valueChanges.subscribe(fn);
  }

  setDisabledState(disabled: boolean) {
    disabled ? this.form.disable() : this.form.enable();
  }

  registerOnTouched(fn: () => void) {
    this.onTouched = fn;
  }
}

【问题讨论】:

标签: angular angular-reactive-forms


【解决方案1】:

方法1:(使用事件发射器)

export class AddressFormComponent implements ControlValueAccessor {
   @Output formValidStatus = new EventEmitter<any>();

   this.formValidStatus.emit(true);
}

父组件模板:

<app-address-form (formValidStatus)="formValidStatus($event)" formControlName="address"></app-address-form>

父组件:

formValidStatus(){
  //update form status
}

方法二:

使用 Angular DI 在子组件构造函数中注入 ParentComponent。您可以在子组件中调用父方法。

constructor(private appc: AppComponent){} 

this.appc.methodname();

【讨论】:

    【解决方案2】:

    将您的地址控件更改为 formGroup 并在那里添加验证

    constructor(private fb: FormBuilder) {
        this.form = fb.group({
          name: fb.control('foo bar', Validators.required),
          address: fb.control({
            city: 'baz',
            town: 'qux',
          })
        });
      }
    

    应该是这样的:

     constructor(private fb: FormBuilder) {
        this.form = fb.group({
          name: fb.control('foo bar', Validators.required),
          address: fb.group({
            city: ['box',Validators.required],
            town: ['qux',Validators.required],
          })
        });
      }
    

    https://stackblitz.com/edit/save-7ucjtn

    【讨论】:

    • 主窗体不会意识到嵌套组件中动态添加的控件。
    • 目前还不错。但是还是有错误。错误:control.registerOnChange 不是函数
    猜你喜欢
    • 1970-01-01
    • 2021-04-02
    • 2019-06-04
    • 2017-07-21
    • 1970-01-01
    • 2021-12-06
    • 2018-01-21
    • 2018-11-04
    • 2017-08-04
    相关资源
    最近更新 更多