Search code examples
angularangular5angular6angular-reactive-formsangular-forms

Angular 6 Reactive Forms Custom Validator Error Displayed from it's OWN data


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 Same data as previous one

Image 2: Change the Position select value and the Error Disappears Position changed and Error Disappears

Image 3: Enter some number in Pay Rate input and the Error displays again. Input payrate changes and Error Appears


Solution

  • 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 :

    1. You don't have any uniqueid on row level, I have added as index of your 'this.addPay' length. See Line number : 57 and 75.
    2. applied condition in the 'getJobLocDeptValidity' method to check index of current control and filter index should not be same and did some other changes.

    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.