Search code examples
angularangular-reactive-formsangular-formsangular-formbuilder

Show Error if Total Min Value Is Not Equal to Max Value


I need to show the error if the total min value is not equal to the total max value. How will i able to do it? Here's my code and the link below PLEASE CLICK THIS LINK

this.total$ = this.inquiryForm.valueChanges.pipe(
      startWith(this.inquiryForm.value),
      map(f => f.rows.reduce(
        (acc, q) =>
          ({
            min: +acc.min + +q.min,
            max: +acc.max + +q.max
          }),
        { min: 0, max: 0 }
      ))
    );

Solution

  • You should simply be able to add a boolean property to the component and tap() the calculated total to set the value:

    in public property section, add:

    minEqualsMax = true;
    

    In ngOnInit():

    this.total$ = this.inquiryForm.valueChanges.pipe(
          startWith(this.inquiryForm.value),
          map(f => f.rows.reduce(
            (acc, q) =>
              ({
                min: +acc.min + +q.min,
                max: +acc.max + +q.max
              }),
            { min: 0, max: 0 }
          )),
          tap(total => { this.minEqualsMax = total.min === total.max; }),
        );
    

    Then it's simply a matter of adding your message to the template with a *ngIf="!minEqualsMax"

    However, this will not stop the form submit as nothing is added to the form validation. If you need that, I'd suggest writing a custom validator function which iterates the rows FormArray to calculate values and return an appropriate error if their sums aren't equal.

    A custom validator could be as simple as:

    const MinEqualsMaxValidator: ValidatorFn = (array: FormArray): { [key: string]: boolean } => {
    
      const total = array.value
        .reduce((total, val) => (total.min+=+val.min, total.max+=+val.max, total), {min:0,max:0})
      const valid = total.min === total.max;
    
      return valid ? null : { minEqualMax: true };
    };
    

    Add this into the form by including it as a second argument when building the rows FormGroup: ie rows: formBuilder.group([], MinEqualsMaxValidator).

    Then you can include an error message in the form using something like this (to be added to the bottom of your current table):

    <tr *ngIf="inquiryForm.rows.invalid && (inquiryForm.controls.rows.dirty || inquiryForm.controls.rows.touched || inquiryForm.submitted)">
      <td colspan="4">
        Validation Error!
        <div *ngIf="inquiryForm.controls.rows.errors.minEqualMax">Error: min does not equal max!</div>
      </td>
    </tr>
    

    I hope this helps!