Forms 向动态构造的表单添加验证 脚本

Forms 向动态构造的表单添加验证 脚本,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]=

我正在开发一个savedialog,它可以接受任何带有字符串、布尔值和日期字段的简单对象。我已经构建了一个组件来处理这个组件的构建,现在我想动态地向已经创建的输入字段添加验证

我正在用TypeScript编程,使用Angular2和一个叫做PrimeNG的框架,PrimeFaces的Angular2版本

我现在的代码 Html

<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">