嵌套的反应形式始终有效

时间:2018-12-15 09:54:14

标签: angular angular-reactive-forms

我使用嵌套的反应形式作为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;
  }
}

2 个答案:

答案 0 :(得分: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
}

方法2:

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

constructor(private appc: AppComponent){} 

this.appc.methodname();

答案 1 :(得分:0)

将地址控件更改为formGroup并在其中添加验证

d = {0: ("A",), 1: ("BB",), 2: ("BB",), 3: ("D",), 4: ("E",)}
l = [(0, 1, 2, 4), (3,)]

output = defaultdict(set)

for key_group in l:
    output[key_group].update(d[key] for key in key_group)

应该是:

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

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