问题
I have to find if one of my formcontrols has a pattern error. If it has a pattern error, then I have to change the value of that formcontrol to null.
I wrote a recursive method that calls itself to check if one f the form control has a pattern error and then it finally returns true or false, But what I want is to change the value of that formcontrol to null
Here is my recursive function,
hasPatternError(form: AbstractControl, isRecursion = false): boolean {
if (!isRecursion) {
this.patternErrors = [];
}
if (form instanceof FormControl) {
return form.hasError('pattern') === true ?? null;
}
if (form instanceof FormArray) {
form?.controls?.forEach(e => {
this.hasAnyPatternError(e, true);
});
}
if (form instanceof FormGroup) {
Object.keys(form.controls).forEach(key => {
const error = this.hasAnyPatternError(form.get(key), true);
if (error === true) {
this.patternErrors.push(error);
}
});
return this.patternErrors.length > 0 ? true : false;
}
}
This is my form, listening to value changes event. On the change event, I am calling the above recursive method to find if any of the form control has a pattern error but stuck on changing the value of that formcontrol to null.
Note: I want the method (hasPatternError) to return an object(that has error converted to null and not expecting the form to change realtime)
ngOnInit() {
this.myForm = this.fb.group({
name: [''],
address: this.fb.group({
street: [''],
zip: [''],
licenseNo: ['', [Validators.required, Validators.pattern(/^[a-z0-9]{10}$/i)]],
})
})
this.myForm.valueChanges.subscribe(
data => {
console.log(this.hasAnyPatternError(this.myForm))
}
);
}
Here is my code on stackblitz
回答1:
You already have reference to the form
and the control key
when you push the error.
Set the value on the control at that time.
- Because you are doing this with recursion, it seems to have some odd behavior when I played with it in your stackblitz.
- But the point I wanted to make is that there is a
setValue
function on the control for this, just need to determine the best way to use it in your logic. - Might even need to explore debouncing the behavior etc to allow the user time to finish key strokes.
if (!form.controls[key]['controls'] && error === true) {
setTimeout(()=>{
form.controls[key].setValue('');
},3000)
this.patternErrors.push(error);
}
I added a setTimeout
to wait 3 seconds before setting value back to ''
to simulate debounce... it appears to work, but this is not a proper solution, just illustrates the principal you need to explore to leverage setValue
properly in your recursion.
STACKBLITZ
https://stackblitz.com/edit/ng-nested-formgroup-zet7ry?file=src/app/app.component.ts
回答2:
Instead of returning booleans indicating a pattern error, return the controls that have pattern errors.
findPatternErrors(formItem: AbstractControl): FormControl[] {
if (formItem instanceof FormControl) {
if (formItem.hasError('pattern')) {
return [formItem];
}
return [];
}
if (formItem instanceof FormArray) {
const patternErrors: FormControl[] = [];
formItem.controls?.forEach(arrayItem => {
const ctrls = this.findPatternErrors(arrayItem);
Array.prototype.push.apply(patternErrors, ctrls);
});
return patternErrors;
}
if (formItem instanceof FormGroup) {
const patternErrors: FormControl[] = [];
Object.keys(formItem.controls).forEach(key => {
const ctrls = this.findPatternErrors(formItem.get(key));
if (ctrls.length) {
Array.prototype.push.apply(patternErrors, ctrls);
}
});
return patternErrors;
}
}
https://stackblitz.com/edit/ng-nested-formgroup-fmhfcs?file=src/app/app.component.ts
来源:https://stackoverflow.com/questions/65429846/loop-through-nested-formgroup-and-change-each-form-control-value-to-null-if-it-h