在Angular 2中使用FormArray的ControlValueAccessor

Ano*_* Me 14 forms angular

我有一个子组件,它处理输入控件数组.我希望对子组件进行formcontrol.

我正在传递json对象的数组,这是将父表单绑定到子组件的FormArray的正确方法,它具有2个表单控件,首先需要Validator.

这是初始代码

<h1>Child</h1>
<div formArrayName="names">
 <div *ngFor="let c of names.control">
  <input formControlName="firstName">
  <input formControlName="lastName">
 </div>
</div>
Run Code Online (Sandbox Code Playgroud)

意图是将父表单与子组件中的输入控件数组绑定.如果子组件中的一个输入控件没有必填字段,则表单也将变为无效.

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

Eli*_*seo 5

我喜欢解决旧帖子:)

关键是你自定义的Form Component里面有一个FormArray,然后使用“writeValue”来创建formArray,见stackblitz

@Component({
    selector: "my-child",
    template: `
    <h1>Child</h1>

    <div *ngFor="let group of formArray.controls" [formGroup]="group">
        <input formControlName="firstName" (blur)="_onTouched()" />
        <input formControlName="lastName" (blur)="_onTouched()"/>
    </div>
    `,
    providers: [{
            provide: NG_VALUE_ACCESSOR,
            useExisting: Child,
            multi: true
        },
        {
            provide: NG_VALIDATORS,
            useExisting: Child,
            multi: true
        }
    ]
})
export class Child implements ControlValueAccessor {
    formArray: FormArray;
    _onChange;
    _onTouched;

    writeValue(value: any) {
        this.formArray = new FormArray(
            value.map(x => {
                return new FormGroup({
                    firstName: new FormControl(x.firstName, Validators.required),
                    lastName: new FormControl(x.firstName, Validators.required)
                });
            })
        );
        this.formArray.valueChanges.subscribe(res => {
            this._onChange(res);
        });
    }

    registerOnChange(fn: (value: any) => void) {
        this._onChange = fn;
    }

    registerOnTouched(fn: (value: any) => void) {
        this._onTouched = fn;
    }

    validate({ value }: FormControl) {
        return !this.formArray || this.formArray.valid ?
            null : { error: "Some fields are not fullfilled" };
    }
}
Run Code Online (Sandbox Code Playgroud)


Ser*_*nho 1

您必须使用formArrayName指令,*ngFor如下所示:

<form [formGroup]="form" (ngSubmit)="sayHello()">
       <input formControlName="name"><br>
       <input formControlName="email"><br>
       <div formArrayName="username">
           <div *ngFor="let user of username.controls; let i=index">
                <my-child formControlName="i"></my-child>
           </div>
       </div>
       <button type="submit">Register</button>
</form>
Run Code Online (Sandbox Code Playgroud)

FormBuilder你一起使用FormArray也是如此。

form = new FormGroup({
     name: new FormControl('My Name'),
     username: new FormArray([
                  new FormControl("value"),// ControlValueAccesor is applied only to one control, not two. So you cannot use javascript object like you are using below this line.
                  {firstName:"Anna", lastName:"Smith"},
                  {firstName:"Peter", lastName:"Jones"}
                ])
   });
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,请参阅此文档。

情况2:传递FormGroup:

form = new FormGroup({
     name: new FormControl('My Name'),
     username: new FormArray([
                  new FormGroup({
                        firstName: new FormControl('Anna'),
                        lastName: new FormControl('Smith')
                  }),
                  new FormGroup({
                        firstName: new FormControl('Peper'),
                        lastName: new FormControl('Jones')
                  }),
                ])
   })
Run Code Online (Sandbox Code Playgroud)

如果您尝试将 FormGroup 作为 ngModel 参数传递,则不能!

  • 这怎么可能是反模式,子组件必须驻留在库中并且将被许多页面使用。最好将代码复制粘贴到任何地方,最好创建一个子组件并在许多地方按原样使用它。 (6认同)
  • 当在父组件本身中创建 formArray 时,这很好,但我想要一个带有 formArray 的子组件。 (2认同)