验证未与自定义输入组件一起传播 - Angular 4

Posted

技术标签:

【中文标题】验证未与自定义输入组件一起传播 - Angular 4【英文标题】:validation not propagated with custom input component - Angular 4 【发布时间】:2018-07-04 20:21:33 【问题描述】:

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

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

谢谢! //对不起我的英语!

编辑:我做了一个 plunker: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;
    
  


最后这是一个用途:

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

【问题讨论】:

【参考方案1】:

主要问题是您如何使用 NgModel。您在自定义组件和表单内部都使用它。您应该只在表单中使用它。意思是,textarea 不应该有 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

【讨论】:

谢谢!我已经更新了我的 plunker (plnkr.co/edit/NHc25bo8K9OsgcxSWyds?p=preview),所以通过这种方式,您可以使用自定义验证器类,而不必像以前那样做所有的事情,并且在组件中包含错误消息(我正在寻找的行为为)。

以上是关于验证未与自定义输入组件一起传播 - Angular 4的主要内容,如果未能解决你的问题,请参考以下文章

将 CSS plus 选择器与自定义组件一起使用

在 Angular 中使用 ControlValueAccessor 继承验证

将 Firebase 身份验证与自定义提供程序一起使用

关于AngularJs,数据绑定与自定义验证

如何将 Django 的内置身份验证与自定义表单(html 模板)一起使用

自定义 angular2 表单输入组件,在组件内具有两种方式绑定和验证