【问题标题】:Angular Use Child Component Form in Parent Component Nested FormAngular 在父组件嵌套表单中使用子组件表单
【发布时间】:2020-04-05 17:10:27
【问题描述】:

将 ChildComponent 表单放入父组件表单的最佳方法是什么?我们使用的是 2019 年最新的 Angular 8。以下方法经研究后无法完全发挥作用。

父组件:

 ngOnInit() {
    this.parentForm = this.fb.group({
       childForm1: etc
    })

子组件:

this.ChildForm = this.formBuilder.group({
  'streetNumber': [null, [Validators.required, Validators.maxLength(32)]],
  'streetType': [null, [Validators.maxLength(8)]],
  'city': [null, [Validators.maxLength(32)]],
  'state': [null, [Validators.maxLength(16)]],
  'postalCode': [null, [Validators.maxLength(16)]],
}, { validator: atLeastOneLocationRequired })

}

方法一:

这个方法,https://itnext.io/partial-reactive-form-with-angular-components-443ca06d8419 经过严格的测试表明 ParentForm 是有效的,即使 Child Form 是无效的。这不应该发生。

ngOnInit() {
  this.parent = this.fb.group({
    fullName: null
  })

}

formInitialized(name: string, form: FormGroup) {
  this.checkoutForm.setControl(name, form);
}

方法二:

方法 2 使用 ViewChild,这是一种不好的做法。 https://davembush.github.io/attaching-an-angular-child-component-s-form-to-a-parent/

@ViewChild(ChildComponent) childComponent: ChildComponent;

And now in ngAfterViewInit() we can add the child’s FormGroup as an additional “control” and set the parent FormGroup to the parent control’s FormGroup.

ngAfterViewInit() {
  this.form.addControl('childForm', this.childComponent.form);
  this.childComponent.form.setParent(this.form);
}

那么 Angular 8 中最好的 Angular 官方实践是什么?

【问题讨论】:

  • 我这里做了详细解答stackoverflow.com/a/59285337/2398593
  • 嗨 @maxime1992 这些是父子表单,在两个不同的组件中
  • 另外,尽量不用第三方库
  • “这些是父表单和子表单,在两个不同的组件中”不确定您要实现的目标然后抱歉
  • @Artportraitdesign1 也对孩子使用相同的形式 [form]="form" angular.io/guide/dynamic-form

标签: angular typescript angular-reactive-forms angular8


【解决方案1】:

我已经根据你的问题创建了小场景。

父组件:

HTML:

<form [formGroup]="form">
  <app-child [form]="form"></app-child>
  <pre>{{form.value | json}}</pre>
</form>

TS:

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
  form: FormGroup;
  constructor (private fb: FormBuilder) {}

   ngOnInit() {
    this.form = this.fb.group({
      childForm1: '',
      streetNumber: [null, [Validators.required, Validators.maxLength(32)]],
      streetType: [null, [Validators.maxLength(8)]],
      city: [null, [Validators.maxLength(32)]],
      state: [null, [Validators.maxLength(16)]],
      postalCode: [null, [Validators.maxLength(16)]],
    })
  }
}

子组件:

HTML:

<div [formGroup]="form">
  <input formControlName="streetNumber"><br>
  <input formControlName="streetType"><br>
  <input formControlName="city"><br>
  <input formControlName="state"><br>
  <input formControlName="postalCode">
</div>

TS:

import { Component, OnInit, Input } from '@angular/core';
import { FormGroup } from '@angular/forms';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
   @Input() form: FormGroup;
  constructor() { }

  ngOnInit() {
  }

}

工作链接:https://stackblitz.com/edit/angular-gjrphg

更新了多个孩子的链接:https://stackblitz.com/edit/angular-svnqfh?file=src/app/app.component.html

【讨论】:

  • 这种相同的模式是否适用于多个子组件表单转到单个父表单?
  • @Artportraitdesign1 是的,请检查更新的链接(我已经更新了答案)
  • 如果您需要将其嵌套得更深怎么办?假设您有一个用于 postalCode 的子组件,但您仍想将其保留在父组件 FormGroup 中? (并且不指定父 FormGroup 例如,如果我将 postalCode 组件添加到 app.component 和 secondChild.component?
  • @Mackelito 如果我的观点正确,那么您需要为孩子创建组并将您想要的值放在该场景中父母和孩子是分开的。
  • 我通过使用 NG_VALUE_ACCESSOR 解决了这个问题。所以现在您只需添加 formControlName 的每个组件,它就会“连接”到表单中...... :)
【解决方案2】:

经过多次讨论和反复试验,我的团队确定了几乎是第一种方法,即子组件定义子表单相应的表单组。但是我们没有使用@ViewChild()AfterViewInit 设置表单控件。相反,我们将父表单传递给子组件并让子组件设置链接。这是因为我们有一个子组件,它可能用于许多不同的父组件,并且重复 AfterViewInit sn-p 会很快变老。此外,如果您的父表单包含在 *ngIf-directive 中,则此方法也有效,因为在子组件初始化时而不是之前进行布线(不再需要讨厌的 @ViewChild() set childComponent() {} 恶作剧)。

<!-- parent form -->
<app-child-form [parent]="form"></app-child-form>
// Child component
@Component({
    selector: 'app-child-form',
    templateUrl: './child-form.component.html',
})
export class ChildComponent {
    @Input()
    parent!: FormGroup;

    form: FormGroup;

    constructor(private fb: FormBuilder) {
        this.form = this.fb.group({
            // ...
        });
    }

    ngOnInit() {
        this.parent.addControl('child-form', this.form);
        this.form.setParent(this.parent);
    }
}

【讨论】:

    猜你喜欢
    • 2019-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-04
    • 1970-01-01
    相关资源
    最近更新 更多