0
votes

I have a FormArray in a FormGroup and each of the FormArray has multiple FormGroup's and can add them dynamically.

I have an Async Validator where it needs all the data in the FormGroup to validate the minimum payRate, currently have a dummy Async Validator which doesn't use all the FormGroup values but will need them to make the API call.

The issue comes because if I want all the data of the FormGroup, I need to add the Async Validator to the FormGroup and not the individual FormControl, to which i need to get ng-invalid to have a border-color: red.

StqackBlitz link: https://stackblitz.com/edit/angular-vr4cya-b3r3od

addPay.push(
    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)
    },null,this.payRateValidator.bind(this))
  );

payRateValidator:

payRateValidator(control: AbstractControl): {[key: string]: any} {
const payRate = control.get('payRate').value;
  const location = control.get('location').value;
  const department = control.get('department').value;

const promise = new Promise<any>((resolve, reject) => {
  setTimeout(() => {
    if (payRate <= 13) {
      resolve({'payRateisLess': true});
    } else {
      resolve(null);
    }
  }, 1500);
});
return promise;

}

Can't have the Async Validator for the PayRate FormControl because of the Async Validator function cant access the values of other FormControl in the FormGroup.

addPay.push(
    new FormGroup({
      "payRate": new FormControl(assign.jobRate, Validators.required, this.payRateValidator.bind(this)),
      "position": new FormControl(assign.position, Validators.required),
      "location": new FormControl(assign.location, Validators.required),
      "department": new FormControl(assign.department, Validators.required)
    })
  );

Currently, when I click on +Additional Assignment button, by default, I'm getting Error text, "Please enter Pay Rate >13", but this is not getting hidden when I type value greater than 13, because I need to enter all the inputs in the FormGroup since I have other validators for that are Required.

After I enter all the inputs in the current FormGroup the error message disappears.

Is there any way to only show the error message, just for the Pay Rate Input tag when having Async Validator for the whole FormGroup???.

enter image description here

1
The stackblitz example is not a reactive form. I can provide an answer if you provide the payRateValidator codeAvin Kavish
The general approach here should be to use a factory method that captures the FormGroup in a closure and creates a validator function for the payrate that you then pass in, normally.Avin Kavish
@AvinKavish, I've updated the Stackblitz link and added the payRateValidator. Can you let me know. ThanksVarun

1 Answers

1
votes

The problem that you want solved is not caused by the AsyncValidator. The AsyncValidator is going to cause the entire form to be marked as invalid regardless of where it is placed because the payrate being invalid implies that the formGroup and the Form it is in is also invalid.

To suppress the borders around invalid components you can use,

.cancel-border {
  border: none !important;
}

And apply that to any components that you want to not have an invalid border. Or remove this bit entirely, if it is possible to edit that code:

div.ng-invalid {
  border: 1px solid red;
}

Having said that I have also moved your AsyncValidator function into the payRate control using a factory method:

makeValidator(fg: FormGroup) {
return (control: AbstractControl) => {
  const payRate = fg.get('payRate').value;
  const location = fg.get('location').value;
  const department = fg.get('department').value;

  const promise = new Promise<any>((resolve, reject) => {
    setTimeout(() => {
      if (payRate <= 13) {
        resolve({ 'payRateisLess': true });
      } else {
        resolve(null);
      }
    }, 1500);
  });
  return promise;
}
}

and changed the way the validity is assessed.

<span [hidden]="assign.get('payRate').valid" ...>

There is a bit of code duplication at lines 54 and 70 that should be looked at and the validation message appearing every time a value is changed before disappearing. I think that can be fixed by using an observable instead of a promise.