如何在 angular2 (ReactiveForms) 中添加动态自定义验证?
How to add dynamic custom validations in angular2 (ReactiveForms)?
我有一个要求,我想实现逻辑来动态地将对象数组数据分配给输入控件,并且基于更新我想更新我的数组,我想触发验证以检查是否输入 names/data在具有重复条目的控件中。
为了验证,我使用了 ReactiveForm 模块。但我面临以下 2 个问题 –
- 我如何创建相同的数组结构以便成功
验证我可以直接将更新的结构传递给 api?
- 我如何将数组对象的 id 分配给 formControlName,目前我正在为它分配循环索引。
plunkar 参考这里 - https://plnkr.co/edit/RSBpT0sFSI1GDCp6K7VR?p=preview
组件:
@Component({
selector: 'my-app',
template: `
<div>
<h3> Custom Group Validation</h3>
<form [formGroup]="myForm">
<div class="left">
names: <br>
<div formArrayName="names">
<div *ngFor="let item of namesArray.controls; let i = index">
<input type="text" [formControlName]="i">
<button (click)="removeAt(i)">X</button><br>
</div>
</div>
<div *ngIf="namesArray.hasError('duplicate')">
duplicate entries
</div>
<pre>Array value: <br>{{namesArray.value | json}}</pre>
</div>
</form>
</div>
`
})
Class(摘要):
namesArray:FormArray = new FormArray([], this.customGroupValidation );
dataArray: { custId: number, customerName: string }[] = [
{ custId: 101, customerName: 'John' },
{ custId: 102, customerName: 'Mike' },
{ custId: 103, customerName: 'Julia' }];
ngOnInit():void{
for(let ele of this.dataArray){
this.namesArray.push(
new FormControl(ele.customerName)
);
}
}
感谢任何帮助!
处理这两个问题的一种方法是订阅 FormGroup 的 .valueChanges
事件,并放入检查方法以验证 FormControl 值是否存在重复情况。
在 ngOnInit() 中创建 FormControl 并将其添加到 FormGroup 时也分配 custId 属性
代码片段 -
import { Component, NgModule, OnInit } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormBuilder, FormGroup, FormArray, AbstractControl, Validators, FormControl, ReactiveFormsModule } from '@angular/forms'
@Component({
selector: 'my-app',
template: `
<div>
<h3> Custom Group Validation</h3>
<form [formGroup]="customerFormGroup">
<div class="left">
names: <br>
<div>
<div *ngFor="let item of dataArray">
<input type="text" [formControlName]="item.custId" [(ngModel)]="item.customerName">
<div *ngIf="customerFormGroup.controls[item.custId] && customerFormGroup.controls[item.custId].errors">
duplicate
</div>
</div>
</div>
<pre>Array value: <br>{{dataArray | json}}</pre>
</div>
</form>
</div>
`
})
export class App implements OnInit {
customerFormGroup: FormGroup = new FormGroup({});
dataArray: { custId: number, customerName: string }[] = [
{ custId: 101, customerName: 'John' },
{ custId: 102, customerName: 'Mike' },
{ custId: 103, customerName: 'Julia' }];
ngOnInit(): void {
for (let ele of this.dataArray) {
let control: FromControl = new FormControl(ele.customerName);
this.customerFormGroup.addControl(ele.custId, control);
}
this.customerFormGroup.valueChanges.subscribe(
data => this.onValueChanged(data)
);
}
onValueChanged(data?: any) {
if (!this.customerFormGroup) return;
let formGroup = this.customerFormGroup;
var result = _.groupBy(formGroup.controls, c => {
if (c.value) return c.value.toLowerCase();
else c.value;
});
for (let prop in result) {
if (result[prop].length > 1) {
_.forEach(result[prop], function (item: any) {
if (item.dirty && item.value) {
item.setErrors({
'duplicate': true
});
}
})
}
}
}
}
@NgModule({
imports: [BrowserModule, ReactiveFormsModule],
declarations: [App],
bootstrap: [App]
})
export class AppModule { }
我有一个要求,我想实现逻辑来动态地将对象数组数据分配给输入控件,并且基于更新我想更新我的数组,我想触发验证以检查是否输入 names/data在具有重复条目的控件中。 为了验证,我使用了 ReactiveForm 模块。但我面临以下 2 个问题 –
- 我如何创建相同的数组结构以便成功 验证我可以直接将更新的结构传递给 api?
- 我如何将数组对象的 id 分配给 formControlName,目前我正在为它分配循环索引。
plunkar 参考这里 - https://plnkr.co/edit/RSBpT0sFSI1GDCp6K7VR?p=preview
组件:
@Component({
selector: 'my-app',
template: `
<div>
<h3> Custom Group Validation</h3>
<form [formGroup]="myForm">
<div class="left">
names: <br>
<div formArrayName="names">
<div *ngFor="let item of namesArray.controls; let i = index">
<input type="text" [formControlName]="i">
<button (click)="removeAt(i)">X</button><br>
</div>
</div>
<div *ngIf="namesArray.hasError('duplicate')">
duplicate entries
</div>
<pre>Array value: <br>{{namesArray.value | json}}</pre>
</div>
</form>
</div>
`
})
Class(摘要):
namesArray:FormArray = new FormArray([], this.customGroupValidation );
dataArray: { custId: number, customerName: string }[] = [
{ custId: 101, customerName: 'John' },
{ custId: 102, customerName: 'Mike' },
{ custId: 103, customerName: 'Julia' }];
ngOnInit():void{
for(let ele of this.dataArray){
this.namesArray.push(
new FormControl(ele.customerName)
);
}
}
感谢任何帮助!
处理这两个问题的一种方法是订阅 FormGroup 的 .valueChanges
事件,并放入检查方法以验证 FormControl 值是否存在重复情况。
在 ngOnInit() 中创建 FormControl 并将其添加到 FormGroup 时也分配 custId 属性
代码片段 -
import { Component, NgModule, OnInit } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormBuilder, FormGroup, FormArray, AbstractControl, Validators, FormControl, ReactiveFormsModule } from '@angular/forms'
@Component({
selector: 'my-app',
template: `
<div>
<h3> Custom Group Validation</h3>
<form [formGroup]="customerFormGroup">
<div class="left">
names: <br>
<div>
<div *ngFor="let item of dataArray">
<input type="text" [formControlName]="item.custId" [(ngModel)]="item.customerName">
<div *ngIf="customerFormGroup.controls[item.custId] && customerFormGroup.controls[item.custId].errors">
duplicate
</div>
</div>
</div>
<pre>Array value: <br>{{dataArray | json}}</pre>
</div>
</form>
</div>
`
})
export class App implements OnInit {
customerFormGroup: FormGroup = new FormGroup({});
dataArray: { custId: number, customerName: string }[] = [
{ custId: 101, customerName: 'John' },
{ custId: 102, customerName: 'Mike' },
{ custId: 103, customerName: 'Julia' }];
ngOnInit(): void {
for (let ele of this.dataArray) {
let control: FromControl = new FormControl(ele.customerName);
this.customerFormGroup.addControl(ele.custId, control);
}
this.customerFormGroup.valueChanges.subscribe(
data => this.onValueChanged(data)
);
}
onValueChanged(data?: any) {
if (!this.customerFormGroup) return;
let formGroup = this.customerFormGroup;
var result = _.groupBy(formGroup.controls, c => {
if (c.value) return c.value.toLowerCase();
else c.value;
});
for (let prop in result) {
if (result[prop].length > 1) {
_.forEach(result[prop], function (item: any) {
if (item.dirty && item.value) {
item.setErrors({
'duplicate': true
});
}
})
}
}
}
}
@NgModule({
imports: [BrowserModule, ReactiveFormsModule],
declarations: [App],
bootstrap: [App]
})
export class AppModule { }