2

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

1
  • 1
    Should the Total field really be a field in the Form rather then just a a text output for deposit * quantity? (i guess you should not be able to change it?) -> you could create a getter for this value in your component getTotal(FormGroup) => total Commented Nov 29, 2019 at 14:09

4 Answers 4

3
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>
Sign up to request clarification or add additional context in comments.

5 Comments

I've edited the question, please check now I want the total to be the product of price and quantity
I don't think this will work in my case, because when I will add a new row (please see the attached image to have a better idea) the total will same for all rows. How to deal with this situation. Please Thanks in advance
@MoxxiManagarm, that's can not work. If you use |async you only get the value in a first time -async unsubcribe the observable-
@Eliseo that is not true. The async pipe also refreshes the value. It's not once
You're rigth, sorry my confussion
2

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

2 Comments

looks pretty good, I just saw the stackBlitz example, but its not working in my example
because I've dynamic number of rows, (see the image to get the better idea) i.e. when user will add a new row, will not be the total same in all rows ?
1

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

Comments

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.