Reputation: 3735
I have a FormArray in a FormGroup and each of the FormArray has multiple FormGroup's and can add them dynamically.
I have a Custom Validator where it checks with all the data in each of the FormArray to validate the repetition of data. There's an issue with it, the single FormGroup in FormArray is comparing it to all the data in the FormArray and is returning True since the FormGroup exists inside of the FormArray
StackBlits link: https://stackblitz.com/edit/angular-custom-validator-defaultdata
Problem Steps: Click on Additional Assignment => Select Position, Department and Location same as the previous row. => You'll see the error, "Same Job data " => Now change the value of the Position to something else => No Error => Change the value in the Pay Rate input => You see the error, "Same Job data " > Because it's comparing the changed row to the data from the Form Data which will definitely return True.
Is there any way to restrict the error from throwing itself when it's checking its own data.?
I'm only checking the similarity between Position, Department, and Location.
for (let assign of this.additionalAssign) {
const fg = new FormGroup({
"payRate": new FormControl(assign.jobRate, Validators.required),
"position": new FormControl(assign.position, Validators.required),
"location": new FormControl(assign.location, Validators.required),
"department": new FormControl(assign.department, Validators.required)
});
fg.validator = this.jobDataValidator.bind(this);
this.addPay.push(fg);
}
Validator:
jobDataValidator(control: FormControl): {[s: string]: boolean} {
let value = this.getJobLocDeptValidity(control);
if(value.length > 0 && control.dirty){
return {'sameJobData': true};
}
return null;
}
getJobLocDeptValidity(control: FormControl):any[] {
let additionalAssignments = this.additionalAssignmentsForm.value.payArray;
let test = additionalAssignments.filter(item => !!control.value.position && item.position === control.value.position && !!control.value.department && item.department === control.value.department && !!control.value.location && item.location === control.value.location);
return test;
}
Image 1: New Row (3rd) data same as previous one(2nd) => Error Displayed
Image 2: Change the Position select value and the Error Disappears
Image 3: Enter some number in Pay Rate input and the Error displays again.
Upvotes: 1
Views: 2038
Reputation: 11243
Your implementation looks perfectly fine except the check condition. Since you don't have any unique id for row its difficult to match if the record is existing one or now.
However you are lucky enough to have reference of all required object. You can check if the Object matched or not.
Just add one more condition in validation part
control !== item
Below is the changed code -
getJobLocDeptValidity(control: FormControl):any[] {
let additionalAssignments = this.additionalAssignmentsForm.value.payArray;
let test = additionalAssignments.filter(item =>
control !== item && !!control.value.position && item.position === control.value.position && !!control.value.department && item.department === control.value.department && !!control.value.location && item.location === control.value.location);
return test;
}
Since you have index
and per your comment, below check works.
control.index !== item.i
Upvotes: 2
Reputation: 19
You can try excluding the payRate value from the validator like so:
jobDataValidator(control: FormControl): {[s: string]: boolean} {
let value = this.getJobLocDeptValidity(control);
if(value.length > 0 && control.dirty && !control.value.payRate){
return {'sameJobData': true};
}
return null;
}
Upvotes: 0
Reputation: 390
I have forked your sample application and did some minor changes in the code. now it is working as expected. Please see on stackblitz.
I have done three changes which are listed below :
Here are the code changes of your getJobLocDepValidity.
getJobLocDeptValidity(control: FormControl):any[] {
let additionalAssignments = this.additionalAssignmentsForm.value.payArray;
let test = additionalAssignments.filter(item => {
if(control.value.index != item.index){
return (item.payRate == control.value.payRate && item.position == control.value.position && item.department == control.value.department && item.location == control.value.location)
}
return false;
} );
return test;
}
@Sunil I would suggest, please try to give a correct answer and test it before giving your inputs, So someone can implement easily without any buggy code.
Upvotes: 1