Search code examples
angularangular-reactive-formsangular-validation

Max validator value using the value of another control within a form array


I am hoping the code below explains my need well. I need a max number validator on a count field that checks for the value of another capacity field. An issue I am having is both fields are within a form array of a form group, so there will be many instances of count/capacity combinations. Any help would be greatly appreciated. Using Angular 7.

setForm() {
  this.form = this.fb.group({
    types: this.fb.array([])
  });
  this.typesArray = this.form.get('types') as FormArray;
}

addType() {
  this.typesArray.push(this.setType(0,0));
}

setType(countValue, capacityValue): FormGroup {
  return this.fb.group({
    count: [{value: countValue}, [
      Validators.pattern(/^[0-9]*$/i ),
      Validators.max(WHAT PUT HERE FOR ALWAYS CHECKING VALUE OF CAPACITY??)
    ]],
    capacity: [{value: capacityValue}, Validators.pattern(/^[0-9]*$/i )],
  });
}

I would expect the validation message to show in the UI if the count field is greater than capacity field at any time of editing either of the fields. This would be a connection only between each instance of both.


Solution

  • when you try to validate a form control based on another form control the best case is to create custom formgroup validator

    custom validator

    export function maxValueValidator(fb: FormGroup): ValidationErrors | null {
      const count = +fb.get('count').value || 0;
      const capacity = +fb.get('capacity').value;
    
      if (capacity > count) {
        return {
          maxValue:
          {
            count,
            capacity
          }
        }
      } else {
        null
      }
    
    }
    

    add the validator to the formGroup

    this.form = fb.group({
      count: null,
      capacity: [null,]
    }, {  // 👈 after we have finished set the controls we add formGroup validators
        validators: [maxValueValidator] 
      });
    

    }

    stackblitz demo 🚀