验证未使用自定义输入组件传播 - 角度 4



我有一个自定义的文本区域组件,里面有文本区域输入。我创建了一个自定义验证器来检查文本的最大长度(不是 html 长度(。一切正常,问题是内部输入设置为无效(带有 ng-invalid(,而 che 组件本身没有,因此包含组件的表单仍然有效。它似乎与内置的必需验证器一起使用,该验证器同时放置在组件和输入上。

如何使自定义输入中的更改反映在外部表单上?

谢谢!对不起我的英语!

编辑:我做了一个笨蛋:https://plnkr.co/edit/NHc25bo8K9OsgcxSWyds?p=preview

这是自定义文本区域组件 html:

<textarea
  [disabled]='disabled'
  [required]='required'
  [placeholder]="placeholder"
  (changes)="onInput($event)"
  (keyup)="onInput($event)"
  [(ngModel)] = "data"
  [name]="name"
  #input="ngModel"
  customMaxLength="{{maxLength}}"
></textarea>
<span *ngIf="input.errors && (input.dirty || input.touched)">
  <span *ngIf="input.errors?.required" class="error-message">Required!</span>
  <span *ngIf="input.errors?.customMaxLength" class="error-message">Max Length Reached({{maxLength}})</span>
</span>

这是组件的代码

import { Component, Input, forwardRef, ViewChild } from '@angular/core';
import { NgModel, ControlValueAccessor, NG_VALUE_ACCESSOR, AbstractControl } from '@angular/forms';
@Component({
  selector: 'custom-text-area',
  templateUrl: './custom-text-area.component.html',
  styleUrls: ['./custom-text-area.component.less'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => TextAreaComponent),
      multi: true
    }
  ]
})
export class TextAreaComponent implements ControlValueAccessor{
  @Input() required = false;
  @Input() name;
  @Input() data;
  @Input() disabled;
  @Input() placeholder = '';
  @Input() errorMsg;
  @Input() maxLength = null;
  @ViewChild('input') input: NgModel;
  constructor() {
    this.data = '';
  }
  propagateChange = (_: any) => {};
  writeValue(value: any): void {
    if (value !== undefined) {
      this.data = value;
    } else {
      this.data = '';
    }
  }
  registerOnChange(fn: any): void {
    this.propagateChange = fn;
  }
  registerOnTouched(fn: any): void {}
  setDisabledState?(isDisabled: boolean): void {
    this.disabled = isDisabled;
  }
  onInput(e) {
    this.data = e.target.value || '';
    this.propagateChange(this.data);
  }
}

这是验证器

import { NG_VALIDATORS, Validator, FormControl } from '@angular/forms';
import { Directive, forwardRef, Input } from '@angular/core';
@Directive({
  selector: '[customMaxLength][ngModel]',
  providers: [
    { provide: NG_VALIDATORS, useExisting: forwardRef(() => MaxLengthValidatorDirective), multi: true}
  ]
})
export class MaxLengthValidatorDirective implements Validator{
  @Input() customMaxLength: number;
  ngOnInit(){
  }
  validate(c: FormControl): { [key: string]: any; } {
    if(c.value && this.customMaxLength){
      return c.value.length <  this.customMaxLength ? null : { customMaxLength:{ valid: false } };
    } else {
      return null;
    }
  }
}

Aaand 最后这是一个用途:

<form #form="ngForm">
    <custom-text-area [maxLength]="3" required ngModel name="textArea"></custom-text-area>
</form>

主要问题是你如何使用NgModel。您可以在自定义组件和窗体中使用它。您应该只在表单中使用它。这意味着,文本区域不应该有NgModel。

不:

<textarea
  [disabled]='disabled'
  [required]='required'
  [placeholder]="placeholder"
  (changes)="onInput($event)"
  (keyup)="onInput($event)"
  [(ngModel)] = "data"
  [name]="name"
  #input="ngModel"
  customMaxLength="{{maxLength}}"
></textarea>

是的:

<textarea
  [disabled]='disabled'
  [required]='required'
  [placeholder]="placeholder"
  (changes)="onInput($event)"
  (keyup)="onInput($event)"
  [name]="name"
  customMaxLength="{{maxLength}}"
></textarea>

这是一个工作示例:

https://plnkr.co/edit/lWZpEpPdnfG7YDiH21jB?p=preview

最新更新