Mr Khan
Mr Khan

Reputation: 2292

Angular Async custom validator for formArray

I have a form that has dynamic fields of amount for which I am using formArray. The user can generate multiple fields of the amount.

What I want is to calculate the total values in all dynamic fields and show an error message if the total amount is exceeded.

The problem is when I looped over the FormArray with value change and then returned a promise on resolve but it only shows the validation error for the first field. Below is the StackBlitz. You can see it in the console. When you type some number that exceeds the total it will show error for the first field. For the rest, if you exceed the total it doesn't show an error. https://stackblitz.com/edit/angular-sbidt3

Upvotes: 0

Views: 682

Answers (1)

MoxxiManagarm
MoxxiManagarm

Reputation: 9124

You shouldn't use valueChanges. What you are actually looking for is cross-form-validation.

Read about it, e.g.: https://medium.com/@realTomaszKula/angular-cross-field-validation-d94e0d063b61 https://angular.io/guide/form-validation

Bind the validator to the form


Edited:

Component

  biddingForm: FormGroup;

  constructor( private _formBuilder: FormBuilder,) { }

  ngOnInit() {
    this.biddingForm = this._formBuilder.group({
      bidding: this._formBuilder.array([]),
    }, { validator: this.amountValidator });

    this.addBet();
  }

  addBet(){
    this.bidding.push(
      this._formBuilder.control(0),
    );
  }

  get bidding(){
    return <FormArray>this.biddingForm.controls.bidding;
  }

  amountValidator(fg: FormGroup) {
    const values: number[] = (fg.controls.bidding as FormArray).controls.map(
      (control: FormControl) => +control.value, 
    );

    const amount = values.reduce((sum, v) => sum + v, 0);

    return amount <= 50 ? null : { amount: true };
  };

Template

<form [formGroup]="biddingForm">
  <div formArrayName="bidding">
    <div class="col-75" *ngFor="let bet of bidding.controls; let i = index;">
        <input [formControlName]="i" type="text"  required > 
        <div *ngIf="biddingForm.hasError('amount')">
          Maxmimum amount reached
        </div>
      </div>
  </div>
  <button (click)="addBet()">Add</button>
</form>

Upvotes: 2

Related Questions