【发布时间】:2019-06-12 17:15:18
【问题描述】:
通常,当我在响应式表单中进行复杂验证时,我会为那些相互依赖的控件定义一个 formGroup。
这在上述场景中是不可能的,我们有 3 steps = 3 groups 和依赖的 3 个字段 firstUnique, secondUnique, thirdUnique。
<form [formGroup]="myForm">
<mat-horizontal-stepper formArrayName="formArray" #stepper>
<mat-step formGroupName="0" [stepControl]="formArray?.get([0])" errorMessage="Name is required.">
<ng-template matStepLabel>Fill out your name</ng-template>
<mat-form-field>
<input matInput placeholder="Last name, First name" formControlName="firstCtrl" required>
</mat-form-field>
<mat-form-field>
<input matInput placeholder="UNIQUE1" formControlName="firstUnique" required>
</mat-form-field>
<div>
<button mat-button matStepperNext>Next</button>
</div>
</mat-step>
<mat-step formGroupName="1" [stepControl]="formArray?.get([1])" errorMessage="Address is required.">
<ng-template matStepLabel>Fill out your address</ng-template>
<mat-form-field>
<input matInput placeholder="Address" formControlName="secondCtrl" required>
</mat-form-field>
<mat-form-field>
<input matInput placeholder="UNIQUE2" formControlName="secondUnique" required>
</mat-form-field>
<div>
<button mat-button matStepperPrevious>Back</button>
<button mat-button matStepperNext>Next</button>
</div>
</mat-step>
<mat-step formGroupName="2" [stepControl]="formArray?.get([2])" errorMessage="Error!">
<ng-template matStepLabel>Done</ng-template>
You are now done.
<div>
<mat-form-field>
<input matInput placeholder="UNIQUE3" formControlName="thirdUnique" required>
</mat-form-field>
<button mat-button matStepperPrevious>Back</button>
<button mat-button (click)="stepper.reset()">Reset</button>
</div>
</mat-step>
</mat-horizontal-stepper>
我使用SO_answer 和Material_docs 描述的技术
我的解决方案目前正在运行,但我对它不满意:
- 在启动时
Unique Validation运行一千次(30-40 次)(hacky) - 在整个步进器中 ANY 输入的 EVERY 变化时,
Unique Validation被触发。 (这是因为我必须将它添加到整个 formGroup)。 一个简单的任务,因为这 3 个输入字段需要是唯一的,这已经变成了一个样板和复杂的混乱。 (请关注
function Unique(arr: string[]))当
UNIQUE Validator使正确的步骤无效或STEP 再次有效时,不会调用STEPPER-VALIDATION。 (例如:firstUnique = "a", secondUnique "b", thirdUnique = "a" (再次)
我的表单
this.myForm = this._formBuilder.group({
formArray:
this._formBuilder.array([
this._formBuilder.group({
firstCtrl: [''],
firstUnique: [''],
}),
this._formBuilder.group({
secondCtrl: [''],
secondUnique: [''],
}),
this._formBuilder.group({
thirdUnique: [''],
})
])
}, {
validator: [Unique(['0;firstUnique', '1;secondUnique', '2;thirdUnique'])]
});
独特的验证器乐趣
function Unique(arr: string[]) {
const validKey = "uniqueValid";
return (formGroup: FormGroup) => {
const myValues =
arr.map(path => {
const s = path.split(';');
return (<FormArray>formGroup.get('formArray'))
.controls[parseInt(s[0])]
.controls[s[1]];
});
const myKeys = arr.map(path => path.split(';')[1] )
const obj = {};
myKeys.forEach(function (k, i) {
obj[k] = myValues[i];
})
myKeys.forEach((item, index) => {
debugger
console.log('unique validation function runs')
const control = obj[item];
const tmp = myKeys.slice();
tmp.splice(index,1);
const ans = tmp
.filter( el => obj[item].value === obj[el].value)
if ( ans.length && control.value ) {
const err = {}
err[validKey] = `identicial to: ${ans.join(', ')}`
control.setErrors(err);
} else if ( obj[item].errors && !obj[item].errors[validKey] ) {
return;
} else {
control.setErrors(null);
}
})
}
【问题讨论】:
标签: angular forms angular-material mat-stepper