просто customValidator над массивом. В любом случае в вашем коде есть ошибка типа, посмотрите на stackblitz
ngOnInit() {
this.bookFg = this.fb.group({
arrayForm: this.fb.array(
this.allBooks.map(book =>
this.fb.group({
id: [book.id],
name: [book.name],
active: [book.active]
})
)
)
});
}
myCustomValidator() {
return (formArray: FormArray) => {
let valid: boolean = true;
formArray.value.forEach((x, index) => {
if (formArray.value.findIndex(y => y.name == x.name) != index)
valid = false;
});
return valid ? null : { error: "Names must be unique" };
};
}
Обновление Вы также можете создать валидатор только для полей "name"
myCustomValidatorName(index) {
return (formControl: FormControl) => {
let valid: boolean = true;
if (index) {
const formArray =
formControl.parent && formControl.parent.parent
? (formControl.parent.parent as FormArray)
: null;
if (formArray) {
console.log(formControl.value);
formArray.value.forEach((x, i) => {
if (x.name == formControl.value && index>i) valid = false;
});
}
}
return valid ? null : { error: "Names must be inique" };
};
}
И вы создаете форму, подобную
ngOnInit() {
this.bookFg = this.fb.group({
arrayForm: this.fb.array(
this.allBooks.map((book, i) =>
this.fb.group({
id: new FormControl(book.id),
name: new FormControl(book.name, this.myCustomValidatorName(i)),
active: new FormControl(book.active)
})
),
this.myCustomValidator()
)
});
}
Но проблема в том, что при смене имени не проверять чужое имя. поэтому вы должны создать функцию
checkArray(index) {
(this.bookFg.get("arrayForm") as FormArray).controls.forEach((x, i) => {
if (i != index) x.get("name").updateValueAndValidity();
});
}
и вызвать (вход) редактирования - или подписаться на valuesChange-
<input formControlName="name" (input)="checkArray(i)">
Обновить как проверить наsubmit или on blur
Для проверки при submit или blur нам нужно создать форму с конструктором formGroup и FormControl, а не с FormBuilder, добавив {updateOn:'blur'}
или {updateOn:'submit'}
в конце новой FormGroup (*)в этом случае используйте (размытие) на входе
this.bookFg = new FormGroup({
arrayForm: new FormArray(
this.allBooks.map((book, i) =>
this.fb.group({
id: new FormControl(book.id),
name: new FormControl(book.name,this.myCustomValidatorName(i)),
active: new FormControl(book.active)
})
),
this.myCustomValidator()
)
},{updateOn: 'blur'}); //<--this