Lint
Lint

Reputation: 935

How to bind form input value in reactive form

I want the value of total box equivalent to the product of price and quantity. Without reactive form it was quite easy by using banana in box syntax. How do I achieve the same in reactive-forms

here is my form code

addProductFormGroup(): FormGroup {
    return this._formBuilder.group({
      productId: ['', Validators.required],
      price: ['', Validators.required],
      loanTermId: ['', Validators.required],
      quantity: ['', Validators.required],
      deposit: ['', Validators.required],
      total: ['', Validators.required],
    });
  }

and here is the html of total input

<mat-form-field appearance="outline" fxFlex="100" class="pr-4">

    <mat-label>Total </mat-label>
        <input type='number' value='deposit*quantity' formControlName="total" [id]="'total' + i" matInput name="" id="" placeholder="Total" required>

</mat-form-field>

image of my form form image

Upvotes: 2

Views: 1864

Answers (4)

mithushancj
mithushancj

Reputation: 96

Let me know if this works out (Link to StackBlitz)

ngOnInit(){

this.formGroup =  this.fb.group({
  quantity : [0 ,[]],
  value:[0,[]],
  total:[0]
})

this.formGroup.valueChanges.pipe(
  debounceTime(500),
  distinctUntilChanged(this.isSame)
).subscribe(values =>{
  console.log(values)
  const {value, quantity} = values;
  this.formGroup.patchValue(
    {
      total : value * quantity
    }
  )
})}

isSame(prev, next) {
  return (prev.value === next.value)
 && (prev.quantity === next.quantity);
}

https://stackblitz.com/edit/angular-8t3qpo?embed=1&file=src/app/app.component.ts

Upvotes: 2

Andrew Allen
Andrew Allen

Reputation: 8002

You could subscribe to value changes similar to the following:

    // build formgroup then ...

    // calculate total
    this.formGroup.valueChanges
      .pipe(debounceTime(20), takeUntil(this.destroyed$))
      .subscribe(value => {
        this.calculateLineItemTotal();
      });
  private calculateLineItemTotal(): number {
    // get quantity and rate values
    const quantity = +this.formGroup.controls.LineQuantity.value;
    const rate = +this.formGroup.controls.LineRate.value;

    // verify if blank
    if (!quantity || !rate) {
      this.formGroup.controls.LineTotal.setValue("", {
        emitEvent: false
      });
      return 0;
    }

    this.formGroup.controls.LineTotal.setValue((quantity * rate).toFixed(2), {
      emitEvent: false
    });
    return quantity * rate;
  }

Warning - This gets ugly fast (think patching value when in edit mode) so best avoided if possible as alluded to be Jenson in the comments.

Upvotes: 1

MoxxiManagarm
MoxxiManagarm

Reputation: 9124

value='33' // dont do that


addProductFormGroup(): FormGroup {
    return this._formBuilder.group({
      productId: ['', Validators.required],
      price: ['', Validators.required],
      loanTermId: ['', Validators.required],
      quantity: ['', Validators.required],
      deposit: ['', Validators.required],
      total: ['33', Validators.required], // do that!
    });
  }

Edited:

Based on your response, I'd say remove total from the formGroup since it is not actually a user input. Rather do something liek this:

total$: Observable<number>;

this.total$ = this.productFormGroup.valueChanges.pipe(
  map(formValue => +formValue.quantity * +formValue.price)
)

<div>Total: {{ total$ | async }}</div>

Upvotes: 3

Chintan Kukadiya
Chintan Kukadiya

Reputation: 784

I think you just need to do something like

public get total(): any {
   if (this.form.get('price').value && this.form.get('quantity').value) {
       return this.form.get('price').value * this.form.get('quantity').value;
   }
   return '';
}

Note : You need to create form and need to store formGroup return value in that

Upvotes: 1

Related Questions