Angular 2:带验证的自定义输入组件(反应/模型驱动方法)

时间:2016-11-28 18:39:55

标签: forms validation angular

我必须创建一个带有自定义输入元素组件(以及组件内部的更多元素,但这不是问题而不是此处示例的一部分)组件内外的强>反应/模型驱动方法和验证

我已经创建了组件,它运行正常,我的问题是formControl(在子级和父级内)在验证或触摸状态时都不同步。例如,如果键入的字符串超过10个字符,则表单内的表单控件将是stil有效。

Plunkr

//our root app component
import {Component, Input} from '@angular/core'
import { 
  FormControl,
  FormGroup,
  ControlValueAccessor,
  NG_VALUE_ACCESSOR,
  Validators
} from '@angular/forms';


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

  <h1>Child</h1>
  <input [formControl]="childControl">
  `,
  providers: [
    {provide: NG_VALUE_ACCESSOR, useExisting: Child, multi: true}
  ]
})

export class Child implements ControlValueAccessor {
  childControl = new FormControl('', Validators.maxLength(10));

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

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

  registerOnTouched() {}
}


@Component({
  selector: 'my-app',
  template: `
    <div>
      <h4>Hello {{name}}</h4>
      <form [formGroup]="form" (ngSubmit)="sayHello()">
       <my-child formControlName="username"></my-child>
       <button type="submit">Register</button>
      </form>
      {{form.value | json }}
    </div>
  `
})
export class App {

  form = new FormGroup({
    username: new FormControl('username', Validators.required)
  });

  constructor() {
    this.name = 'Angular2';
  }

  sayHello() {
    console.log(this.form.controls['username'])
  }

}

我不知道如何以正确的方式解决这个问题

1 个答案:

答案 0 :(得分:0)

存在来自Angular的Validator接口,用于将验证转发给父级。您需要使用它,并使用forwardRef将NG_VALIDATORS提供给组件装饰器的providers数组:

{
  provide: NG_VALIDATORS,
  useExisting: CustomInputComponent,
  multi: true
}

您的组件需要实现Validator接口:

class CustomInputComponent implements ControlValueAccessor, Validator,...

,并且您必须提供Validator接口的方法的实现,至少是validate方法的实现:

  validate(control: AbstractControl): ValidationErrors | null {
    return this.formGroup.controls['anyControl'].invalid ? { 'anyControlInvalid': true } : null;
  } 

当输入更改时,还有另一个同步验证器:

  registerOnValidatorChange(fn: () => void): void {
    this.validatorChange = fn;
  }