gga*_*bor 4 validation angular2-forms angular
我试图找出为ngModel实现自定义验证器逻辑的最简单方法.我有一个预定义的模型(接口),它存储当前数据,所以我不想处理新的FormGroup/FormControl(模型驱动)方法.
如果我已经拥有了我需要的所有数据,为什么要使用FormControls构建完全相同的模式?
这是我的代码(https://plnkr.co/edit/fPEdbMihRSVqQ5LZYBHO):
import { Component, Input } from '@angular/core';
export interface MyWidgetModel {
title:string;
description:string;
}
@Component({
selector: 'my-widget',
template: `
<h4 *ngIf="!editing">{{data.title}}</h4>
<input *ngIf="editing" type="text" name="title" [(ngModel)]="data.title">
<p *ngIf="!editing">{{data.description}}</p>
<textarea *ngIf="editing" name="description" [(ngModel)]="data.description" (ngModelChange)="customValidator($event)"></textarea>
<button (click)="clickEditing()">{{editing ? 'save' : 'edit'}}</button>
`
styles: [
':host, :host > * { display: block; margin: 5px; }',
':host { margin-bottom: 10px; padding-bottom: 10px; border-bottom: 1px solid #eee; }',
'.ng-invalid { background-color: #FEE; }'
]
})
export class MyWidgetComponent {
@Input() data:MyWidgetModel;
constructor() {
this.editing = false;
}
clickEditing() {
this.editing = !this.editing;
}
customValidator(value:string) {
console.log(this, value); //should be: MyWidgetComponent
//How to set 'invalid' state here?
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,我可以快速打开/关闭编辑模式,我可以直接编辑我的数据.
我的问题是如何直接从我的组件管理ngModel的ng-valid/ng-invalid状态?这背后的想法包含多个要点:
最后我想出了办法.我认为这是最简单的.我还更新了plunker:https://plnkr.co/edit/fPEdbMihRSVqQ5LZYBHO
让我们一步一步看.
1 - 创建一个简单的最小指令,实现Validator接口 - 与往常一样 - 但不要编写任何验证逻辑.而是提供函数类型的Input()字段 - 与选择器同名.这将允许我们在此验证器之外实现真正的逻辑.在validate(...)函数内部只调用外部Input()函数.
import { Directive, forwardRef, Input } from '@angular/core';
import { AbstractControl, NG_VALIDATORS, Validator, ValidatorFn } from '@angular/forms';
@Directive({
selector: '[myvalidator][ngModel],[myvalidator][ngFormControl]',
providers: [{
multi: true,
provide: NG_VALIDATORS,
useExisting: forwardRef(() => MyValidator)
}]
})
export class MyValidator implements Validator {
@Input() myvalidator:ValidatorFn; //same name as the selector
validate(control: AbstractControl):{ [key: string]: any; } {
return this.myvalidator(control);
}
}
Run Code Online (Sandbox Code Playgroud)
2 - 要使用自定义验证器,只需将其导入并添加到组件的指令数组中.在模板标记中使用它像任何其他指令:
<input type="text" name="title" [(ngModel)]="data.title" [myvalidator]="validateTitle()">
Run Code Online (Sandbox Code Playgroud)
诀窍就在这里.传递给验证器的Input()函数的值是函数调用 - 它将返回验证器函数.这里是:
validateTitle() {
return <ValidatorFn>((control:FormControl) => {
//implement a custom validation logic here.
//the 'this' points the component instance here thanks to the arrow syntax.
return null; //null means: no error.
});
Run Code Online (Sandbox Code Playgroud)
以上所有与官方Angular2验证器完全兼容 - 必需,模式等 - 因此我们的自定义验证器可以在没有任何进一步技巧的情况下进行组合.
编辑: 如果在组件的构造函数中为每个验证创建局部变量,则可以实现更简单有效的方法:
private validateTitle:ValidatorFn;
constructor() {
this.validateTitle = (control:FormControl) => {
//implement a custom validation logic here.
//the 'this' points the component instance here thanks to the arrow syntax.
return null; //null means: no error.
};
}
Run Code Online (Sandbox Code Playgroud)
使用这种方法,我们只创建一次ValidatorFn函数,而不是每个验证请求.1个函数调用eleminated:validateTitle().所以在模板中我们可以绑定我们的变量:
<input type="text" name="title" [(ngModel)]="data.title" [myvalidator]="validateTitle">
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8350 次 |
| 最近记录: |