检查 Angular 反应形式的 FormGroups 字段中是否有重复项
Check if there is a duplicate item in FormGroups field in Angular reactive form
在保存我所有的网格行时,我需要检查特定列字段是否存在重复项
(this.formGroups.get('items') as FormArray).controls.forEach((item) => {
console.log(item.value.attributeDisplayName);
});
当 attributeDisplayName
有重复值时,我需要通过显示警告或类似内容来阻止提交表单。我如何在当前的 forEach 循环中检查它。谢谢
我在我的 HTML 标记中使用 kendo angular 组件,但我没有使用表单标签。下面是列声明的示例
<kendo-grid-column field="attributeDisplayName" title="CUSTOM FIELD LABEL" width="190">
<ng-template kendoGridEditTemplate let-column="column" let-formGroup="formGroup" >
<input ngDefaultControl class="k-textbox" [formControl]="formGroup.get(column.field)">
<div *ngIf="formGroup.get(column.field).errors && (formGroup.get(column.field).dirty || formGroup.get(column.field).touched)">
<span style="color:red" class="k-icon k-i-warning"></span>
<span style="color:red">CUSTOM FIELD LABEL is a required field</span>
</div>
</ng-template>
</kendo-grid-column>
下面是 .ts 文件中的 FormGroup 声明
public formGroup: FormGroup;
public formGroups: FormGroup = new FormGroup({ items: new FormArray([]) });
public createFormGroup = (dataItem) =>
new FormGroup({
atrributeId: new FormControl(dataItem.atrributeId),
objectType: new FormControl(dataItem.objectType, Validators.required),
attributeDisplayName: new FormControl(dataItem.attributeDisplayName, Validators.required),
dataType: new FormControl(dataItem.dataType, Validators.required),
inputValues: new FormControl(dataItem.inputValues, [Validators.required, InputValuesValidator]),
isGridEligible: new FormControl(dataItem.isGridEligible, Validators.required),
isInvoiceEligible: new FormControl(dataItem.isInvoiceEligible, Validators.required),
});
我使用此 FormGroup 的示例函数
public editRows(grid) {
this.isEdited = true;
let currentRow = 0;
let rows: any = grid.data.data;
for (let i = 0; i < rows.length; i++) {
const formGroup = this.createFormGroup(rows[i]);
this.formGroup = formGroup;
(this.formGroups.get('items') as FormArray).push(formGroup);
grid.editRow(currentRow, formGroup, {skipFocus: true});
currentRow++;
}
}
不是在提交时检查它,只是在填写表单时检查它,如果用户填写了重复值,则立即显示错误。
使用此功能检查重复项 -
checkDuplicacy(event, field: FormControl) {
let length = this.formGroups.value.items.length;
let count = 0;
let controls = (<FormArray>this.formGroups.controls.items).controls;
for (let i = 0; i < length; i++) {
if (
this.formGroups.value.items[i].attributeDisplayName.toLowerCase() ==
event.target.value.toLowerCase()
) {
count++;
}
if (count > 1) {
field.markAsTouched();
field.setValidators((f) => <any>{ duplicateName: true });
field.updateValueAndValidity();
} else {
field.clearValidators();
field.setValidators([Validators.required]);
field.updateValueAndValidity();
}
}
}
并更新了 HTML -
<kendo-grid-column field="attributeDisplayName" title="CUSTOM FIELD LABEL" width="190">
<ng-template kendoGridEditTemplate let-column="column" let-formGroup="formGroup" >
<input ngDefaultControl class="k-textbox" [formControl]="formGroup.get(column.field)" (blur)="checkDuplicacy($event, formGroup.get(column.field))">
<div *ngIf="formGroup.get(column.field).errors && (formGroup.get(column.field).dirty || formGroup.get(column.field).touched)">
<span style="color:red" class="k-icon k-i-warning"></span>
<span style="color:red">CUSTOM FIELD LABEL is a required field</span>
</div>
<span *ngIf="formGroup.get(column.field).errors?.duplicateName" style="color:red">
Duplicate field.</span>
</ng-template>
</kendo-grid-column>
当然,您可以使用验证器来检查重复项。验证器就像
validateUniq(index) {
return (control: AbstractControl) => {
if (control.value) {
//search the "formArray"
const formArray = control.parent
? (control.parent.parent as FormArray)
: null;
if (formArray) {
//we create an array with the attributeDisplayNames
const attributes = formArray.value.map((x) => x.attributeDisplayName);
//only give error if there're duplicate before our
//control
return attributes.indexOf(control.value)>=0 &&
attributes.indexOf(control.value)<index
? { duplicateName: true }
: null;
}
}
};
}
您可以像这样创建 formGroup - 看看您如何传递“索引”
initFormField() {
const index = this.items ? this.items.length : 0;
return this.fb.group({
attributeDisplayName: [
'',
[Validators.required, this.validateUniq(index)],
],
});
}
当我们在控件上使用 Validator 时的问题是只有当控件发生变化时才会检查,所以我们需要像@Shyam 说的那样创建一个函数 checkDuplicacy - 但在这种情况下更简单:
checkDuplicacy(index) {
this.items.controls.forEach((x,i)=>{
if (index!=i)
(x as FormGroup).get('attributeDisplayName').updateValueAndValidity()
})
}
完成拼图的最后一块是获取控件的函数
getAtributeDisplayNameAt(index: number) {
return this.items
? (this.items.at(index).get('attributeDisplayName') as FormControl)
: null;
}
还有一个html喜欢
<form [formGroup]="formGroups" novalidate autocomplete="off">
<div formArrayName="items">
<div
*ngFor="let item of items.controls; let index = index"
[formGroupName]="index"
>
<div class="form-control">
<input
placeholder="Enter here"
formControlName="attributeDisplayName"
(input)="checkDuplicacy(index)"
/>
<span
*ngIf="getAtributeDisplayNameAt(index)?.errors?.duplicateName"
class="error"
>
Duplicate field.</span
>
</div>
</div>
</div>
<button (click)="addFormField()">Add More</button>
</form>
看看我们如何在事件 input
中调用函数 checkDuplicacy
- 你也可以订阅控件的 valueChange
在保存我所有的网格行时,我需要检查特定列字段是否存在重复项
(this.formGroups.get('items') as FormArray).controls.forEach((item) => {
console.log(item.value.attributeDisplayName);
});
当 attributeDisplayName
有重复值时,我需要通过显示警告或类似内容来阻止提交表单。我如何在当前的 forEach 循环中检查它。谢谢
我在我的 HTML 标记中使用 kendo angular 组件,但我没有使用表单标签。下面是列声明的示例
<kendo-grid-column field="attributeDisplayName" title="CUSTOM FIELD LABEL" width="190">
<ng-template kendoGridEditTemplate let-column="column" let-formGroup="formGroup" >
<input ngDefaultControl class="k-textbox" [formControl]="formGroup.get(column.field)">
<div *ngIf="formGroup.get(column.field).errors && (formGroup.get(column.field).dirty || formGroup.get(column.field).touched)">
<span style="color:red" class="k-icon k-i-warning"></span>
<span style="color:red">CUSTOM FIELD LABEL is a required field</span>
</div>
</ng-template>
</kendo-grid-column>
下面是 .ts 文件中的 FormGroup 声明
public formGroup: FormGroup;
public formGroups: FormGroup = new FormGroup({ items: new FormArray([]) });
public createFormGroup = (dataItem) =>
new FormGroup({
atrributeId: new FormControl(dataItem.atrributeId),
objectType: new FormControl(dataItem.objectType, Validators.required),
attributeDisplayName: new FormControl(dataItem.attributeDisplayName, Validators.required),
dataType: new FormControl(dataItem.dataType, Validators.required),
inputValues: new FormControl(dataItem.inputValues, [Validators.required, InputValuesValidator]),
isGridEligible: new FormControl(dataItem.isGridEligible, Validators.required),
isInvoiceEligible: new FormControl(dataItem.isInvoiceEligible, Validators.required),
});
我使用此 FormGroup 的示例函数
public editRows(grid) {
this.isEdited = true;
let currentRow = 0;
let rows: any = grid.data.data;
for (let i = 0; i < rows.length; i++) {
const formGroup = this.createFormGroup(rows[i]);
this.formGroup = formGroup;
(this.formGroups.get('items') as FormArray).push(formGroup);
grid.editRow(currentRow, formGroup, {skipFocus: true});
currentRow++;
}
}
不是在提交时检查它,只是在填写表单时检查它,如果用户填写了重复值,则立即显示错误。
使用此功能检查重复项 -
checkDuplicacy(event, field: FormControl) {
let length = this.formGroups.value.items.length;
let count = 0;
let controls = (<FormArray>this.formGroups.controls.items).controls;
for (let i = 0; i < length; i++) {
if (
this.formGroups.value.items[i].attributeDisplayName.toLowerCase() ==
event.target.value.toLowerCase()
) {
count++;
}
if (count > 1) {
field.markAsTouched();
field.setValidators((f) => <any>{ duplicateName: true });
field.updateValueAndValidity();
} else {
field.clearValidators();
field.setValidators([Validators.required]);
field.updateValueAndValidity();
}
}
}
并更新了 HTML -
<kendo-grid-column field="attributeDisplayName" title="CUSTOM FIELD LABEL" width="190">
<ng-template kendoGridEditTemplate let-column="column" let-formGroup="formGroup" >
<input ngDefaultControl class="k-textbox" [formControl]="formGroup.get(column.field)" (blur)="checkDuplicacy($event, formGroup.get(column.field))">
<div *ngIf="formGroup.get(column.field).errors && (formGroup.get(column.field).dirty || formGroup.get(column.field).touched)">
<span style="color:red" class="k-icon k-i-warning"></span>
<span style="color:red">CUSTOM FIELD LABEL is a required field</span>
</div>
<span *ngIf="formGroup.get(column.field).errors?.duplicateName" style="color:red">
Duplicate field.</span>
</ng-template>
</kendo-grid-column>
当然,您可以使用验证器来检查重复项。验证器就像
validateUniq(index) {
return (control: AbstractControl) => {
if (control.value) {
//search the "formArray"
const formArray = control.parent
? (control.parent.parent as FormArray)
: null;
if (formArray) {
//we create an array with the attributeDisplayNames
const attributes = formArray.value.map((x) => x.attributeDisplayName);
//only give error if there're duplicate before our
//control
return attributes.indexOf(control.value)>=0 &&
attributes.indexOf(control.value)<index
? { duplicateName: true }
: null;
}
}
};
}
您可以像这样创建 formGroup - 看看您如何传递“索引”
initFormField() {
const index = this.items ? this.items.length : 0;
return this.fb.group({
attributeDisplayName: [
'',
[Validators.required, this.validateUniq(index)],
],
});
}
当我们在控件上使用 Validator 时的问题是只有当控件发生变化时才会检查,所以我们需要像@Shyam 说的那样创建一个函数 checkDuplicacy - 但在这种情况下更简单:
checkDuplicacy(index) {
this.items.controls.forEach((x,i)=>{
if (index!=i)
(x as FormGroup).get('attributeDisplayName').updateValueAndValidity()
})
}
完成拼图的最后一块是获取控件的函数
getAtributeDisplayNameAt(index: number) {
return this.items
? (this.items.at(index).get('attributeDisplayName') as FormControl)
: null;
}
还有一个html喜欢
<form [formGroup]="formGroups" novalidate autocomplete="off">
<div formArrayName="items">
<div
*ngFor="let item of items.controls; let index = index"
[formGroupName]="index"
>
<div class="form-control">
<input
placeholder="Enter here"
formControlName="attributeDisplayName"
(input)="checkDuplicacy(index)"
/>
<span
*ngIf="getAtributeDisplayNameAt(index)?.errors?.duplicateName"
class="error"
>
Duplicate field.</span
>
</div>
</div>
</div>
<button (click)="addFormField()">Add More</button>
</form>
看看我们如何在事件 input
中调用函数 checkDuplicacy
- 你也可以订阅控件的 valueChange