Angular4:如何在动态添加属性后重新初始化表单控件

Angular4: How to re-initialize form control after adding an attribute on the fly

所以,我制作了一个带有 "extra" 参数的表单输入组件,我可以在其中设置一些额外的输入属性,如下所示:

  <form-input
    type="text"
    name="email"
    label="Form control 1"
    placeholder="Please enter your email"
    [(ngModel)]="demo.name"
    ngDefaultControl
    [extra] = "{minlength:2}"
  ></form-input>

并在来源中:

  @ViewChild('input') private _inputEl: ElementRef;

  constructor() { }

  ngOnChanges(changes: SimpleChanges){
    if(changes['extra']){
      if(this._inputEl && this._inputEl.nativeElement){
        let attrs = Object.keys(this.extra);
        attrs.forEach(attr => {
          this._inputEl.nativeElement.setAttribute(attr, this.extra[attr]);
        });
      }
    }
  }

视图是这样的:

<div class="form-group">
  <label for="name">{{label}}</label>
  <input
    #input
    [name]="name"
    [type]="type"
    [value]="value"
    class="form-control"
    [(ngModel)]="ngModel"
    [placeholder]="placeholder"
    #name="ngModel"
  >


  <div [hidden]="name.valid || name.pristine" class="alert alert-danger">
    Lorem text
  </div>
</div>

但是,angular 验证不会针对输入框启动....但在检查器中我看到属性设置正确。

如果我将 minlength 直接放入输入元素,验证工作正常

minlength 不仅仅是添加到 HTML 元素的属性,它是将控件添加到关联的 FormControl :

的指令

来自Angular 4 sources

export const MIN_LENGTH_VALIDATOR: any = {
  provide: NG_VALIDATORS,
  useExisting: forwardRef(() => MinLengthValidator),
  multi: true
};

/**
 * A directive which installs the {@link MinLengthValidator} for any `formControlName`,
 * `formControl`, or control with `ngModel` that also has a `minlength` attribute.
 *
 * @stable
 */
@Directive({
  selector: '[minlength][formControlName],[minlength][formControl],[minlength][ngModel]',
  providers: [MIN_LENGTH_VALIDATOR],
  host: {'[attr.minlength]': 'minlength ? minlength : null'}
})
export class MinLengthValidator implements Validator,
    OnChanges {
  private _validator: ValidatorFn;
  private _onChange: () => void;

  @Input() minlength: string;

  ngOnChanges(changes: SimpleChanges): void {
    if ('minlength' in changes) {
      this._createValidator();
      if (this._onChange) this._onChange();
    }
  }

  validate(c: AbstractControl): ValidationErrors|null {
    return this.minlength == null ? null : this._validator(c);
  }

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

  private _createValidator(): void {
    this._validator = Validators.minLength(parseInt(this.minlength, 10));
  }
}

遗憾的是,您不能对元素即时应用指令。

我担心要走的路是实现您自己的验证指令,该指令将处理您传递的对象。您可以以提供的代码为基础来执行此操作,这听起来不是一个巨大的挑战。