I'm very simply trying to validate a control if its value matches a value within a FormArray.
I want to be clear that I do not want to validate the form or a FormGroup or a FormArray. This question is for learning how to pass parameters to a validator function and the validation of the addValue
control.
Here is what I have in my custom validation service:
public form: FormGroup = this.fb.group({
addValue: this.fb.control(null, [this.validatorService.duplicate(this.form.get('values'))]),
values: this.fb.array([])
});
And the validator function
public duplicate(values: FormArray): ValidatorFn {
return (control: AbstractControl): { [key: string]: boolean } | null => {
for (let i = 0, j = values.length; i < j; i++ ) {
if (control.value === values[i].value) {
return { 'duplicate': true };
}
}
return null;
};
}
At this point I get an error where I add the validator with the FormArray as an argument:
Argument of type 'AbstractControl' is not assignable to parameter of type 'FormArray'. Type 'AbstractControl' is missing the following properties from type 'FormArray': controls, at, push, insert, and 5 more.ts(2345) (property) FormGroup.controls: { [key: string]: AbstractControl; }
Can someone show me how to send a FormArray into a validator function?
Here is a Stackblitz of the validator NOT getting the FormArray
Validating Angular FormArray First you need to add the required validators while creating a new product form group inside the addProduct method. Now let's add a span element adjacent to the input control. Add the following CSS to the app. component.
We can add Validators dynamically using the SetValidators or SetAsyncValidators. This method is available to FormControl, FormGroup & FormArray. There are many use cases where it is required to add/remove validators dynamically to a FormControl or FormGroup.
A FormArray will be called validated only if its FormControl or FormGroup are validated. To provide a custom error messages on UI, we can fetch FormArray validation status in HTML template. On this page we will create a reactive form using FormBuilder and then we will validate and submit the form.
However, there may be form fields that require more complex or custom rules for validation. In those situations, you can use a custom validator. When using Reactive Forms in Angular, you define custom validators with functions.
To access validation state of FormArray and its elements, find the getter method for employees form array control. get employees(): FormArray { return this.teamForm.get('employees') as FormArray; } Now in HTML template we can access FormArray validation errors for custom error messages as following.
A FormArray is called validated only if its FormControl or FormGroup are validated. We can validate FormArray with synchronous and async validators. On this page we will create a reactive form using FormBuilder and validate it.
AbstractControl is the base class, simply cast you it:
public form: FormGroup = this.fb.group({
addValue: this.fb.control(null, [this.validatorService.duplicate(this.form.get('values') as FormArray)]),
values: this.fb.array([])
});
you could also sends values directly:
this.validatorService.duplicate(this.form ? this.form.get('values').value : []);
and
public duplicate(values: string[]): ValidatorFn {
return (control: AbstractControl): { [key: string]: boolean } | null => {
for (let i = 0, j = values.length; i < j; i++ ) {
if (control.value === values[i]) {
return { 'duplicate': true };
}
}
return null;
};
}
Instead add a form Validator:
this.form = this.fb.group({
addValue: this.fb.control(null),
values: this.fb.array(['test2', 'test3'])
}, { validator: this.validatorService.duplicate2 });
using this code:
public duplicate2(control: AbstractControl): ValidationErrors | null {
const newValue = control.get('addValue') ? control.get('addValue').value : null;
const values = control.get('values') ? control.get('values').value : [];
console.log("1 " + newValue);
console.log(values);
for (let i = 0, j = values.length; i < j; i++ ) {
if (newValue === values[i]) {
return { 'duplicate2': true };
}
}
return null;
}
and also change your validation:
<app-validator [control]="form"></app-validator>
see https://stackblitz.com/edit/send-validator-formarray-l8j7ys
you can pass the field names as parameter to the validator.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With