Angular2-使用旧数据的自定义验证器 [英] Angular2 - Custom validator using old data

查看:36
本文介绍了Angular2-使用旧数据的自定义验证器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写的自定义验证器有问题.验证器用于验证组件中的所有数据.

I'm having an issue with a custom validator that I've written. The validator is used to validate all the data in a component.

这是设置:

该组件显示具有X行数据的表.其中一些行是仅显示模式,其他行将处于编辑模式(表中的某些单元格将具有输入,选择等).支持该表的是一组数据对象(tableData).

The component displays a table with X rows of data. Some of the rows are display-only mode and others will be in edit mode (certain cells in the table will have inputs, selects, etc). Backing the table is an array of data objects (tableData).

如果一行处于编辑模式,则将每个输入双向绑定到tableData数组中的相应元素.

If a row is in edit mode, each input is two-way bound to the appropriate element in the tableData array.

我的自定义验证器应用于form标记,并采用tableData作为输入.一切都正常.验证数据将查看表中的每一行,并完成我需要做的所有事情.

My custom validator is applied to the form tag and takes tableData as input. Everything mostly works. The validation data looks at each row in the table and does everything I need it to do.

问题在于,基于我的自定义验证器的数据是旧数据.因此,如果一行处于编辑模式,则当我在select中更改值时,tableData会更新,但是传递给验证器的版本是在更新之前.因此,我始终在验证tableData的旧版本.

The issue is that the data based to my custom validator is old data. So if a row is in edit mode, when I change a value in a select, tableData is updated, but the version of it that's passed to the validator is before the update. So I'm always validating an old version of tableData.

我不确定如何获取验证以使用tableData的最新版本.我认为问题可能与以下事实有关:选择绑定更改了tableData数组中对象的值,但tableData数组本身实际上并未更改.

I'm not sure how to get the validation to use the up to date version of tableData. I think the issue may be related to the fact that the select binding changes a value of an object in the tableData array, but the tableData array itself doesn't actually change.

我尝试将回调添加到正在编辑的行中的select的(change)事件上.名为on(更改)的方法使用ChangeDetectorRef手动触发更改检测,但这没有用.

I tried adding callback to the (change) event on the select in the row being edited. The method called on (change) manually triggers change detection using a ChangeDetectorRef, but that didn't work.

我不想向所有人发送全部文件,所以我尝试添加重要的代码片段.

I don't want to spam everyone with all the entire files, so I've tried to just add the important snippets.

这是模板:

<form #f="ngForm" novalidate custom-validator="{{tableData | json}}">
    <p-dataTable [value]="tableData">
    ...

        <p-column [header]="'Program Name'">
            <template let-row="rowData" let-idx="rowIndex" pTemplate type="body">
            <span *ngIf="!row['edit']">
                {{row['data'].programName}}
            </span>
                <div *ngIf="row['edit']">
                    <select #progName="ngModel" [(ngModel)]="row['data'].programCode"
                            title="Select Program" required (change)="onProgramChange($event, idx)"
                            name="programSelect-{{idx}}">
                        <option [value]=""></option>
                        <option *ngFor="let prog of programList" [value]="prog.code">
                            {{prog.name}}
                        </option>
                    </select>
                </div>
            </template>
        </p-column>
    ...

    </p-dataTable>
</form>

这是支持组件:

//imports...

...

private tableData: PersonAssignmentRowData[] = [];
private programList: Program[] = [];

...

onProgramChange(event: any, index: number) {

    for(let prog of this.programList) {
        if(prog.code == event.target.value) {
            this.tableData[index].data.programAcronym = prog.acronym;
            this.tableData[index].data.programLocation = prog.location;
            this.tableData[index].data.programName = prog.name;
            break;
        }
    }
}

...

这里是验证者:

@Directive({
    selector: '[custom-validator]',
    providers:[{provide: NG_VALIDATORS, useExisting: CustomValidator, multi: true}]
})
export class CustomValidator implements Validator{

    @Input('custom-validator') tableDataString: string;

    validate(control: AbstractControl) {
        if(this.tableDataString == null || this.tableDataString.length == 0) {
            return null;
        }

        let tableData: PersonAssignmentRowData[] = [];
        tableData = JSON.parse(this.tableDataString);

        let message: string = '';

        //logic that tests the validity of the data and sets any error messages in the message variable

        if(message.length > 0) {
            return {'validationMessage': message};
        } else {
            return null;
        }
    }
}

推荐答案

现在很清楚.当然,这是行不通的.验证器应检查的唯一数据源是传递给validate()方法的控件.没有@Inputs()或任何类似的东西.唯一的不同是,下面的control.value将包含表单中所有控件的所有值,而不仅仅是表,因此您应该在表所在的位置选择正确的嵌套值.

Now it's clear. Of course it will not work. The only data source that the validator should check is a control that's passed to validate() method. No @Inputs() or anything of the kind. The only difference is that control.value below will contain all values of all controls in the form, not just your table, so you should pick the correct nested value where your table is.

@Directive({
    selector: '[custom-validator]',
    providers:[{provide: NG_VALIDATORS, useExisting: forwardRef(() => CustomValidator), multi: true}]
})
export class CustomValidator implements Validator {

    validate(control: AbstractControl) {
        tableData = control.table.value; // need to figure out exact path based on your form structure

        let message: string = '';

        //logic that tests the validity of the data and sets any error messages in the message variable

        if(message.length > 0) {
            return {'validationMessage': message};
        }
        return null;
    }

}

这篇关于Angular2-使用旧数据的自定义验证器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆