Forms 向动态构造的表单添加验证 脚本
我正在开发一个savedialog,它可以接受任何带有字符串、布尔值和日期字段的简单对象。我已经构建了一个组件来处理这个组件的构建,现在我想动态地向已经创建的输入字段添加验证 我正在用TypeScript编程,使用Angular2和一个叫做PrimeNG的框架,PrimeFaces的Angular2版本 我现在的代码 HtmlForms 向动态构造的表单添加验证 脚本,forms,validation,angular,typescript,primeng,Forms,Validation,Angular,Typescript,Primeng,我正在开发一个savedialog,它可以接受任何带有字符串、布尔值和日期字段的简单对象。我已经构建了一个组件来处理这个组件的构建,现在我想动态地向已经创建的输入字段添加验证 我正在用TypeScript编程,使用Angular2和一个叫做PrimeNG的框架,PrimeFaces的Angular2版本 我现在的代码 Html <p-dialog #dialog header="{{dialogTitle}}" [(visible)]="isDisplayed" [responsive]=
<p-dialog #dialog header="{{dialogTitle}}" [(visible)]="isDisplayed" [responsive]="true" showEffect="fade"
[modal]="true" [closable]="false" [closeOnEscape]="false" [modal]="true" [width]="1000" [resizable]="false">
<form novalidate #form (ngSubmit)="save()">
<div class="ui-grid ui-grid-responsive ui-fluid" *ngIf="saveObject">
<div *ngFor="let i of rows" class="ui-grid-row">
<div class="ui-grid-col-6" *ngFor="let field of fields | slice:(i*itemsPerRow):(i+1)*itemsPerRow">
<div class="ui-grid-col-5 field-label">
<label for="attribute">{{field.key}}</label>
</div>
<div class="ui-grid-col-5">
<p-checkbox *ngIf="booleanFields.indexOf(field.key) !== -1" binary="true"
[(ngModel)]="saveObject[field.key]" name="{{field.key}}"
[ngClass]="{'error-border-class': field.key.errors && (field.key.dirty || field.key.touched)}"
[valueValidator]="field.key" [validateObject]="saveObject"></p-checkbox>
<p-calendar *ngIf="dateFields.indexOf(field.key) !== -1" [(ngModel)]="saveObject[field.key]"
name="{{field.key}}"
[ngClass]="{'error-border-class': field.key.errors && (field.key.dirty || field.key.touched)}"
dateFormat="dd/mm/yy" [showIcon]="true" [appendTo]="dialog"
[monthNavigator]="true"
[ngClass]="{'error-border-class': field.key.errors && (field.key.dirty || field.key.touched)}"
[valueValidator]="field.key"
[validateObject]="saveObject"></p-calendar>
<input *ngIf="(booleanFields.indexOf(field.key) === -1) && (dateFields.indexOf(field.key) === -1)"
pInputText id="attribute" [(ngModel)]="saveObject[field.key]" name="{{field.key}}"
[ngClass]="{'error-border-class': field.key.errors && (field.key.dirty || field.key.touched)}"
[valueValidator]="field.key" [validateObject]="saveObject"/>
</div>
</div>
</div>
</div>
</form>
<p-footer>
<div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix">
<button label=" " type="button" pButton (click)="hideDialog(true)">
<i class="fa fa-times fa-fw" aria-hidden="true"></i>Sluit
</button>
<button label=" " type="submit" pButton (click)="hideDialog(false)" [disabled]="!form.valid">
<i class="fa fa-check fa-fw" aria-hidden="true"></i>Opslaan
</button>
</div>
</p-footer>
我的问题
首先,我想说谢谢你一路读到这篇文章,你是冠军!我知道我的代码不是你见过的写得最漂亮的代码,但我现在只是想让它发挥作用。目前我遇到的问题是验证发生了,但我似乎无法使用
[ngClass]="{'error-border-class': field.key.errors && (field.key.dirty || field.key.touched)}"
发现field.key没有问题,但我似乎无法将其用作输入字段的动态名称的引用。field.key.errors未定义,我想这是意料之中的。但我还没有找到解决办法
第二,我认为我现在的方式将导致整个表单的验证出现问题(禁用提交按钮)
欢迎提出任何关于如何解决此问题的建议,我愿意接受所有建议。请查看。有角度的形状对类型不是特别友好。推荐MobX/React查看一下。有角度的形状对类型不是特别友好。推荐MobX/React
import { Directive, Input } from '@angular/core';
import { AbstractControl, ValidatorFn, Validator, NG_VALIDATORS, FormControl } from '@angular/forms';
@Directive({
selector: '[valueValidator][ngModel]',
providers: [
{provide: NG_VALIDATORS, useExisting: ValueValidatorDirective, multi: true}
]
})
export class ValueValidatorDirective implements Validator {
@Input('valueValidator') fieldName:string;
@Input() validateObject:any;
@Input() values:any[];
datumStartValidator:ValidatorFn;
datumEindValidator:ValidatorFn;
codeValidator:ValidatorFn;
naamValidator:ValidatorFn;
volgNrValidator:ValidatorFn;
validate(c:FormControl) {
this.instantiateFields();
switch (this.fieldName) {
case 'datumStart':
return this.datumStartValidator(c);
case 'datumEind':
return this.datumEindValidator(c);
case 'code':
return this.codeValidator(c);
case 'naam':
return this.naamValidator(c);
case 'volgnr':
return this.volgNrValidator(c);
default :
return {
error: {
valid: false
}
}
}
}
instantiateFields() {
this.datumStartValidator = validateStartDatum(this.validateObject['datumEind']);
this.datumEindValidator = validateEindDatum(this.validateObject['datumStart']);
this.codeValidator = validateCode();
this.naamValidator = validateNaam();
this.volgNrValidator = validateVolgNr(null);
}
}
//We'll need multiple validator-functions here. one for each field.
function validateStartDatum(datumEind:Date):ValidatorFn {
return (c:AbstractControl) => {
let startDatum:Date = c.value;
let isNotNull:boolean = startDatum !== null;
let isBeforeEind:boolean = false;
if (isNotNull) {
isBeforeEind = datumEind.getTime() > startDatum.getTime();
}
if (isNotNull && isBeforeEind) {
return null
} else {
return returnError();
}
}
}
function validateEindDatum(startDatum:Date):ValidatorFn {
return (c:AbstractControl) => {
let eindDatum:Date = c.value;
let isNotNull:boolean = eindDatum !== null;
let isBeforeEind:boolean = false;
if (isNotNull) {
isBeforeEind = eindDatum.getTime() > startDatum.getTime();
}
if (isNotNull && isBeforeEind) {
return null
} else {
return returnError();
}
}
}
function validateCode():ValidatorFn {
return (c:AbstractControl) => {
let code:string = c.value;
if (code !== null) {
return null;
} else {
return returnError();
}
}
}
function validateNaam():ValidatorFn {
return (c:AbstractControl) => {
let naam:string = c.value;
if (naam !== null) {
return null;
} else {
return returnError();
}
}
}
function validateVolgNr(volgnummers:string[]):ValidatorFn {
return (c:AbstractControl) => {
return returnError();
}
}
function returnError():any {
return {
error: {
valid: false
}
}
}
[ngClass]="{'error-border-class': field.key.errors && (field.key.dirty || field.key.touched)}"
<button label=" " type="submit" pButton (click)="hideDialog(false)" [disabled]="!form.valid">