I created a special validator to verify uniqueness in FormArray. I want to show an error when specific values are already in the array.
The problem is that it does not work properly.
Actual behavior:
Steps to play:
- Add 3 "inputs" - address;
- Fill in the input 1;
- Fill in input 2 with a different value;
- Fill input 3 with the same input 1 value; (errors do not appear at input 1 or input 3)
Expected Behavior :
If the same values are displayed in "X-groups", their specific inputs should indicate an error.
In the case described above, errors should appear on inputs 1 and 3.
Suppose I have 4 inputs:
- value: stack
- value: overflow
- value: stack
- value: overflow
4 , .
static uniqueBy = (field: string, caseSensitive = true): ValidatorFn => {
return (formArray: FormArray): { [key: string]: boolean } => {
const controls = formArray.controls.filter(formGroup => {
return isPresent(formGroup.get(field).value);
});
const uniqueObj = { uniqueBy: true };
let found = false;
if (controls.length > 1) {
for (let i = 0; i < controls.length; i++) {
const formGroup = controls[i];
const mainControl = formGroup.get(field);
const val = mainControl.value;
const mainValue = caseSensitive ? val.toLowerCase() : val;
controls.forEach((group, index) => {
if (i === index) {
return;
}
const currControl = group.get(field);
const tempValue = currControl.value;
const currValue = caseSensitive ? tempValue.toLowerCase() : tempValue;
let newErrors;
if ( mainValue === currValue) {
if (isBlank(currControl.errors)) {
newErrors = uniqueObj;
} else {
newErrors = Object.assign(currControl.errors, uniqueObj);
}
found = true;
} else {
newErrors = currControl.errors;
if (isPresent(newErrors)) {
delete newErrors['uniqueBy'];
if (isBlank(newErrors)) {
newErrors = null;
}
}
}
currControl.setErrors(newErrors);
});
}
if (found) {
return uniqueObj;
}
}
return null;
};
}
DEMO
? , .
.