首页 > 解决方案 > 使用Angular 5的具有控件值访问器的子组件中的多个表单控件

问题描述

我想在 Angular 5 中实现一个带有控制值访问器的功能。这就像从父级访问子自定义组件中的多个表单控件。请让我知道我是否可以通过其他方式实现这一目标。模板驱动形式是强制性的。

如果有任何其他可以通用创建具有双向数据绑定的自定义控件,请告诉我。如果答案在 Plunker 或 StackBlitz 中,那就太好了。

这是我的:https ://stackblitz.com/edit/angular-qzioet

父组件:-

export class AppComponent implements OnInit  {
  public countryList: any = [];
  public option: any =[ ];
      public personal = {
   identity: {
  name: {firstname: null, lastname: null },
  age: null,
  sex: null
   }
 }
  @ViewChild('personalForm') form: any;
 constructor() {

   }

父 html:-

<app-input name ='name' [(ngModel)]="personal.identity.name" [form]="personalForm" ngDefaultControl></app-input>

子组件:-

   import {Component, Input, forwardRef} from '@angular/core'
   import { 
    FormControl,
         FormGroup,
    ControlValueAccessor,
    NG_VALUE_ACCESSOR,
        NG_VALIDATORS,
     Validator
         } from '@angular/forms';


    @Component({
 selector: 'app-input',
   templateUrl: "./input-child.html",
          providers: [
{ 
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => Child),
  multi: true
},
{
  provide: NG_VALIDATORS,
  useExisting: forwardRef(() => Child),
  multi: true,
} 
   ]
   })

   export class Child implements ControlValueAccessor, Validator {
 @Input() form: any;
  @Input() name: any;
 childControl = new FormGroup({ firstname: new FormControl() , 
 lastname: new FormControl() });

 fn: (value: any) => void;
 constructor() {
     console.log(this.childControl);
  }

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

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

   registerOnTouched() {}

    validate(c: FormControl) {

        return this.childControl.errors;
        };
    }

子html:-

    `<h1>Child</h1>
    <div>
 <input [formControl]="firstname" (input)="fn($event.target.value)" 
    required>

<input [formControl]="lastname" name="lastname" 
 (input)="fn($event.target.value)" required>

</div>`

标签: angularformsform-controlngmodelcontrolvalueaccessor

解决方案


无需实现 ControlValueAccessor 即可更轻松地实现您想要做的事情。相反,您可以简单地将子组件中的 viewProviders 设置为使用现有的父 NgForm 作为 ControlContainer。

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

输入-child.component.ts:

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

    ...
}

输入-child.component.html:

<h1>Child</h1>
<div>
    <input [(ngModel)]="personalName.firstname" name="firstname" required>
    <input [(ngModel)]="personalName.lastname" name="lastname" required>
</div>

父组件.ts:

export class AppComponent {
    public countryList: any = [];
    public option: any =[ ];
    public personal = {
        identity: {
            name: {firstname: 'first-name', lastname: 'last-name' },
            age: null,
            sex: null
        }
    }

    ...
}

父组件.html:

<form #personalForm="ngForm" name="personalForm">
    <child-input [personalName]="personal.identity.name"></child-input>
</form>

推荐阅读