在父表单中验证表单 Angular 2+

Validating a form within a parent form Angular 2+

假设我有一个包含子地址组件的结帐表单,如下所示

<form [formGroup]="checkoutForm">
  <input formControlName="fullName">
  /** more inputs **/
  <address-form></address-form>
  <button type="submit">Submit</button>
</form>

目前我构建的 checkoutForm 如下:

this.checkoutForm = this.formBuilder.group({
    fullName: ['', Validators.required]
}); 

addressForm 模板如下:

<form [formGroup]="addressForm">
   <input formControlName="street">
   <input formControlName="town"
</form>

并构建为:

this.addressForm = this.formBuilder.group({
  street: ['', [Validators.required]],
  town: ['', Validators.required]
});

现在我遇到的问题是我不知道如何

1 - 仅当子表单有效时才验证父表单。

2 - 在提交父表单时验证子表单。

我能想到的唯一方法是有一个 @Output() addressResponse 将在 this.addressForm.valueChanges 上发出,具有有效性和数据。类似于:

this.addressForm.valueChanges.subscribe(data => {
   let form = this.addressForm.valid ?  
         { valid: true, value: data }: 
         { valid: false, value: data };
   this.addressResponse.emit(form);
});

并且父表单组件可以使用这个发出的数据。

还有一个 @Input() parentFormSubmitted 可以用来显示 AddressForm

模板中的错误
   <input formControlName="town"
   <div *ngIf="town.hasError('required') && (parentFormSubmitted || town.dirty">Town is a required field</div>

虽然这可行,但我不确定这是最佳解决方案。我想知道是否有更多的 Reactive Form 做事方式。 (也许在 CheckoutForm 组的定义中包含 AddressForm 组?...)

您的评论完全正确:

I was wondering if there a more Reactive Form way of doing things. (Maybe include the AddressForm group in the definition of the CheckoutForm group?...)

您可以在 parent 中构建表单,并将嵌套组 address 作为 @Input 传递给 child。由于 JS 中的 objects 是可变的,您不需要 EventEmitter 将任何更改从 child 传递到您的 parent,更改将被捕获 "automatically" 并且因此,您可以从 parent.

进行所有验证

因此,在 parent 中构建您的表单:

this.checkoutForm = this.formBuilder.group({
  fullName: ['', [...]],
  address: this.formBuilder.group({
    street: ['', [...]],
    town: ['', [...]]
  })
})

然后在您的 child 标签中将 address 作为 @Input:

传递给 child
<address-form [address]="checkoutForm.controls.address"></address-form>

在你的 child 中标记 @Input:

@Input() address: FormGroup;

child 中的模板如下所示:

<div [formGroup]="address">
  <input formControlName="street"><br>
  <!-- Validation messages -->
  <input formControlName="town">
  <!-- Validation messages -->
</div>

如前所述,您现在可以处理来自 parent 的所有验证,因为 parent 知道 child 的值:)