I have a from called verification form and a form array called RepDetails with three fields. By default the form shows three fields. User can add more details by clicking on add more. Now I want to check Mydetails[0].name should not match with mydetails[1].name. Can anyone help on this
Myform = this.fb.group({
Mydetails: this.fb.array([this.createMydetails()])
});
createMydetails(): FormGroup {
return this.fb.group({
Myname: ['', Validators.required ],
Myid: ['', Validators.required],
Myphone: ['', Validators.required]
});
}
Html
<div
formArrayName="Mydetails"
*ngFor="let item of Mydetails.controls; let i = index"
>
<div [formGroupName]="i">
<mat-form-field appearance="outline">
<mat-label class="required">
Name
</mat-label>
<input
appAlphaNumeric
[maxlength]="maxRepNamelen"
formControlName="Myname"
class="mat-body-1"
matInput
/>
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label class="required">
Id
</mat-label>
<input
appAlphaNumeric
formControlName="Myid"
class="mat-body-1"
matInput
/>
</mat-form-field>
<div class="phn-wrapper">
<ngx-intl-tel-input
[cssClass]="'int-phn'"
[searchCountryField]="[
SearchCountryField.Iso2,
SearchCountryField.Name
]"name="phone"
formControlName="Myphone"
>
</ngx-intl-tel-input>
</div>
<mat-icon
*ngIf="Mydetails.length > 1"
(click)="remove(i)"
class="close"
>close</mat-icon
>
</div>
</div>
class="add-fields"
(click)="add()"
>
<mat-icon class="icon">add_circle_outline</mat-icon>
<span class="text mat-button">
{{"ADD MORE"}}</span
>
</div>
In this SO you has a custom validation over a FormArray. The problem if you use a custom validation over a formArray is that is checked always you change any value in the formArray (any change in repName, or in passport or in phoneName)
You can create a custom validator over a Form Control that take account others controls
checkIfUnique(index) {
return (control: FormControl) => {
//try get the form array
//control.parent is the FormGroup, control.parent.parent is the formArray
const formArray =
control.parent && control.parent.parent
? (control.parent.parent as FormArray)
: null;
if (formArray && formArray.controls.length) {
for (let i = index - 1; i >= 0; i--) {
if (
(formArray.at(i) as FormGroup).get("repName").value == control.value
)
return { errorRepeat: true };
}
}
};
}
You need, when make the formGroup of the formArray, pass to the validator the "index" of element. So your need change your function createRep
//pass the index
createRep(index:number): FormGroup {
return this.fb.group({
repName: ['', [Validators.required,this.checkIfUnique(index) ]],
passport: ['', Validators.required],
phoneNumber: ['', Validators.required]
});
}
Well, the last we need is, when change a value of any 'repName', check the rest of controls. Remember that Angular check the formControl that you change, but not the rest, so if repName[0]="a"
and repName[1]="b"
, when change repName[0]
to "b" Angular don't check repName[1]
. So we create a function
checkFormArray()
{
this.detailsFormArray.controls.forEach(x=>{
(x as FormGroup).get('repName').updateValueAndValidity()
})
}
//I use a getter of the formArray
get detailsFormArray() {
return (this.verificationForm.get("repDetails") as FormArray)
}
And in the input we call to the function
<input formControlName="repName" (input)="checkFormArray()">
You can see the stackblitz
NOTE: I remove the tag angularjs from your question (your question is only about angular)