Angular ReactiveForms not receiving real-time updates on dynamic values

I'm using reactive forms in Angular and I have a FormArray that retrieves all the values except for product_total.

<tbody formArrayName="products">
  <tr *ngFor="let phone of productForms.controls; let i=index" [formGroupName]="i">
      <th scope="row">{{i+1}}</th>
      <td><input type="text" class="form-control" placeholder="Product Code" formControlName="product_code"></td>
      <td><input type="text" class="form-control" placeholder="Product Name" formControlName="product_name"></td>
      <td><input type="number" class="form-control" placeholder="Price" formControlName="product_price" #price></td>
      <td><input type="number" class="form-control"  formControlName="product_quantity" value="1" #quantity></td>
      <td><input type="number" class="form-control" value="{{(price.value || 0) * (quantity.value || 1)}}" formControlName="product_total" disabled></td>
    </tr>
  </tbody>

How can I fetch the value of product_total for each formgroup within the typescript code? P.S. I am able to access the value within the HTML code, but not in the typescript code.

The corresponding typescript code is as follows:

constructor(private fb: FormBuilder) { }

ngOnInit() {
const product = this.fb.group({
  product_code: [],
  product_name: [],
  product_price: [],
  product_quantity: [1],
  product_total: []
});

this.myForm = this.fb.group({
  customer_name: '',
  customer_phone: '',
  customer_address: '',
  products: this.fb.array([product]),
  subtotal: Number,
  discount: Number,
  cgst: Number,
  sgst: Number,
  total_price: Number,
});
}

get productForms() {
  return this.myForm.get('products') as FormArray;
}


async submitForm() {
    const myForm = this.myForm.value;
    this.invoice = {
      products: myForm.products,
    };
    console.log(this.invoice.products);

  }

Answer №1

Updated Version: The code has been modified, previously it used double curly braces {{ }}, but now we utilize square brackets [value], which eliminates the need for double curly braces. Additionally, the code has been updated to improve functionality.

You don't have to include the total as part of the formGroup anymore.

<input type="number" class="form-control" disabled
    [value]="phone.get('product_price').value *( phone.get('product_quantity').value)" >

In the submit function, you can create a map if necessary.

submit(form){
   if (form.valid)
   {
      let data={
             //include all properties from form.value
             ...form.value,
             //however, 'products' needs to be re-mapped
             products:form.value.products.map(v=>{
             return {
               //For each product, include 
               ...v,   //all properties of products +
               total:v.product_price*v.product_quantity  //total
          }})
        }

      console.log(data);
   }

Answer №2

I had a similar requirement for implementing a piece of logic. I approached it by utilizing the controller and using this code:

ngOnInit() {
    this.formGroup = this.formBuilder.group({
        price: ['', [Validators.required]],
        quantity: ['', [Validators.required]],
        total: ''
    });

    this.formGroup.valueChanges.subscribe(change => {
        this.onPriceChange()
    })
}

onPriceChange() {
    let price = parseFloat(this.formGroup.value.price);
    let quantity = parseInt(this.formGroup.value.quantity);

    if (!isNaN(price) && !isNaN(quantity)) {
        let totalPrice = (price * quantity).toFixed(2);
        this.formGroup.controls['total'].setValue(totalPrice, { emitEvent: false })
    }
}

Updated version to handle FormArray:

Please note the addition of

(ngModelChange)="trackValueChange(i)"
on two inputs:

<tbody formArrayName="products">
    <tr *ngFor="let item of productForms.controls; let i=index" [formGroupName]="i">
        <th scope="row">{{i+1}}</th>
        <td> <input type="text" class="form-control" placeholder="Product Code" formControlName="product_code"></td>
        <td> <input type="text" class="form-control" placeholder="Product Name" formControlName="product_name"></td>
        <td><input type="number" class="form-control" placeholder="Price" formControlName="product_price" #price (ngModelChange)="trackValueChange(i)"></td>
        <td><input type="number" class="form-control" formControlName="product_quantity" value="1" #quantity (ngModelChange)="trackValueChange(i)"></td>
        <td><input type="number" class="form-control" value="{{(price.value || 0) * (quantity.value || 1)}}" formControlName="product_total" disabled></td>
    </tr>
</tbody>

Then, similar to my previous approach, but with indexing on the 'products' array

trackValueChange(index: number){
    let controls = this.formGroup.get('products') as FormArray;
    this.updateTotal(controls[index])
}

updateTotal(control) {
    let price = parseFloat(control.value.product_price);
    let quantity = parseInt(control.value.product_quantity);
    if (!isNaN(price) && !isNaN(quantity)) {
        let totalPrice = (price * quantity).toFixed(2);
        control['product_total'].setValue(totalPrice, { emitEvent: false })
    }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it possible to implement lazy loading for data in TypeScript classes?

Looking to optimize my Angular application's data structure when consuming a RESTful API. My goal is to only load necessary data from the server on demand. For instance, if I have a collection of Building objects each with a set of tenant IDs in an a ...

tips for choosing an entire group in ng-select with Angular

I am implementing a multi-select dropdown with groups in Angular using the ng-select component. My goal is to allow users to select an entire group and have all items within that group automatically selected as well. I have been attempting to model my cod ...

What steps are involved in generating a Typescript module definition for a directory containing a babel-plugin-content-transformer?

Currently utilizing the babel-plugin-content-transformer to import a directory containing YAML documents in a React Native/Expo project. The configuration for my babel plugin looks like this: ['content-transformer', { transformers: [{ ...

Using React with an Array of Promises in Typescript

I have a function that looks like this: function queryProposals(hash:string) { let result = api?.query.backgroundCouncil.proposalOf( hash,(data1:any)=>{ let injectedData = data1.toPrimitive().args.account as InjectedAccou ...

The intended 'this' keyword is unfortunately replaced by an incorrect '

Whenever the this keywords are used inside the onScroll function, they seem to represent the wrong context. Inside the function, it refers to the window, which is understandable. I was attempting to use the => arrow notation to maintain the correct refe ...

Implement a personalized Laravel Dusk selector with the attribute data-dusk

In the world of Laravel Dusk, the default selector hunts for the dusk="something" attribute in your HTML. If you want to dive deeper into this topic, check out this resource. However, when it comes to compatibility with Typescript for React/Vue, ...

tslint is flagging an error related to cyclomatic complexity

Within my Angular 8 project, the following dependencies are utilized: "codelyzer": "^5.1.0", "ts-node": "~8.3.0", "tslint": "~5.19.0", Upon executing: ng lint myapp --fix=true An error is raised stating: ERROR: ...html:428:106 - The cyclomatic complex ...

Imported modules are not being blocked by APP_INITIALIZER

In my Angular application (version 6.0.0), I am working on setting up runtime configuration using APP_INITIALIZER to pull in the configurations. While consulting various articles and Stack Overflow questions, such as this one and that one, I have managed t ...

Can you provide information on the latest stable release of animations for Angular 4?

Encountering an error during npm install Warning - @angular/[email protected] requires a peer of @angular/[email protected] but none was installed. Error encountered during npm start Issue with node_modules/@angular/platform-browser/animations ...

The type of Object.values() is not determined by a union or Records

When utilizing TypeScript, the Object.values() function encounters issues in deducing the accurate type from a union of Records: type A = Record<string, number>; type B = Record<string, boolean>; function func(value: A | B) { const propert ...

I'm baffled by how the community response is implemented in this particular TypeScript exercise on Exercism

I am currently learning TypeScript from scratch by working on exercises available on exercism Successfully completed the 5th exercise on Pangram. Below is my solution: class Pangram { alphabet = "abcdefghijklmnopqrstuvwxyz" constructor(privat ...

What is a way to perform pre-increment without utilizing the ++I operator?

It is my belief that the code snippet below: i += 1 or i = i + 1 does not have the same effect as ++i. Am I incorrect in this assumption? Is there an alternative method to achieve pre-increment without utilizing the ++ operator? ...

Issue encountered during the creation process of a new component within Angular 4

While attempting to create a new component named signup-form using the command: ng generate component signup-form / ng g component signup-form An error is being thrown that reads: Unexpected token / in JSON at position 1154 The source of this error i ...

Struggling to solve a never-ending loop problem in a messaging application

I am currently in the process of developing a chat application. During the initialization of the chat page, I am checking for messages and storing them in an array. ngOnInit() { this.messageService.getMessages().doc(`${this.sortItineraries[0] + ...

Error Message: Angular 5 with SignalR (DefinitelyTyped) - '$' Not Found in Typings

I am currently working on implementing SignalR into my Angular 5 application. To do this, I added the following TypeScript type definitions from DefinitelyTyped: npm install --save @types/jquery npm install --save @types/signalr The version of Typescrip ...

Picture fails to load on Ionic app on the device

Currently, I am utilizing Ionic 3 for my project. The location of the images file is \src\assets\img. This pertains to a basic page implementation. export class BasicPage { items = []; constructor(public nav: NavController ,private adm ...

Is it possible in Typescript to pass method signature with parameters as an argument to another method?

I am working on a React app where I have separated the actions into a different file from the service methods hoplite.actions.ts export const fetchBattleResult = createAsyncThunk<Result>( 'battle/fetchBattleResult', HopliteService.battleRe ...

Struggling to accurately capture the values from checkboxes and dropdown selections to ensure the correct data is displayed. Assistance is needed in this

I am facing challenges in retrieving the accurate data for display from Mat-Select and Mat-Checkbox components. My goal is to capture the selected values from users and perform if-else statements to validate conditions, displaying the correct data view if ...

Switch button - reveal/conceal details

I am looking for assistance in toggling the visibility of information when clicking on an arrow icon. I have attempted to use JavaScript, but it was unsuccessful. My goal is to hide the information below by clicking on the downward-facing arrow image , an ...

Is it possible to use a '.JS' file downloaded through Node Package Manager (npm) directly in a web browser?

Generally, I am looking to utilize a specific library without relying on Node CMD. For instance: I aim to create a TypeScript playground without having to execute 'tsc.cmd' from "npm\node_modules", instead, I want to directly call the tsc c ...