在子组件中使用多个FormControl的ControlValueAccessor

26

我在子组件中有多个表单控件,如何在子组件中应用验证器,使原始表单无效。最好使用ControlValueAccessor实现,但希望从简单的@input表单组开始。

@Component({
  selector: 'my-child',
  template: `

  <h1>Child</h1>
  <div [formGroup]="childForm">
    <input formControlName="firstName">
    <input formControlName="lastName">
  </div>
  `
})

export class Child {
  @Input()
  childForm: FormGroup;
}

http://plnkr.co/edit/K1xAak4tlUKtZmOV1CAQ

3个回答

24

我不知道为什么这个问题被踩了,但我觉得这可能对其他人有帮助,所以我发布了答案。 经过多次尝试绑定子表单组,我成功地绑定了值。

  @Component({
  selector: 'my-child',
  template: `

  <h1>Child</h1>
  <div [formGroup]="name">
    <input formControlName="firstName">
    <input formControlName="lastName">
  </div>
  `,
  providers: [
    {provide: NG_VALUE_ACCESSOR, useExisting: Child, multi: true}
  ]
})

export class Child implements ControlValueAccessor {
  name: FormGroup;
  constructor(fb: FormBuilder) {
    this.name = fb.group({
      firstName:[''],
      lastName: ['']
    });
  }

  writeValue(value: any) {
    if(value) {
        this.name.setValue(value);
    }
  }

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

  registerOnTouched() {}
}

http://plnkr.co/edit/ldhPf7LTFVtTFHe9zfAj?p=preview


10
起初,这对我帮助很大,但后来我发现,我们正在过度复杂化事情。我们不必构建自己的formControl,只需将formGroup传递给子组件即可。 在父组件中,不需要使用

this.form = fb.group({
  name:['Angular2 (Release Candidate!)'],
  username: [{firstName: 'First', lastName: 'Last'}],
  email:['My Email']  
});

我们将用户名(username)初始化为一个FormGroup而不是一个FormControl:

this.form = fb.group({
  name:['Angular2 (Release Candidate!)'],
  username: fb.group({
   firstName: ['First'],
   lastName: ['Last']
  }),
  email:['My Email']
});

在子组件中,我们需要一个FormGroup的输入属性。
@Input()
usernameGroup: FormGroup;

在子模板中:
<div [formGroup]="usernameGroup">
   <input formControlName="firstName">
   <input formControlName="lastName">
</div>

然后在父模板中:

<my-child [usernameGroup]="form.controls.username"></my-child>

了解更多信息,请查看本文:https://scotch.io/tutorials/how-to-build-nested-model-driven-forms-in-angular-2

在这里构建自己的formControl实际上是一种过度设计,想要了解更多信息,请查看这里:http://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html


你知道如何在ngFor中使用子表单吗?Scotch.io教程展示了如何向数组添加内容,但我需要在ngFor内部使用嵌套表单。假设我有一个项目数组,我需要为每个项目添加一个字段,然后将所有这些值汇总到主表单中。 - Adam Mendoza

4

您想要做的事情可以更容易地实现,而无需实现ControlValueAccessor。相反,您只需在子组件中设置viewProviders,将现有的父级NgForm用作ControlContainer。

然后,无需将表单/FormGroup作为输入参数传递给子组件,因为表单控件将自动成为父表单的一部分。

child.component.ts:

@Component({
    selector: 'child',
    templateUrl: './child.component.html',
    viewProviders: [{ provide: ControlContainer, useExisting: NgForm}]
})
export class Child {
    @Input() firstName;
    @Input() lastName;
}

child.component.html:

<h1>Child</h1>
<div>
    <input [(ngModel)]="firstName" name="firstname">
    <input [(ngModel)]="lastName" name="lastname">
</div>

parent.component.html:

<form #personalForm="ngForm" name="personalForm">
    <child [firstName]="firstName" [lastName]="lastName"></child>
</form>

这是唯一正确的答案! - grenobnik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接