0

I am working on reactive forms of angular where I have a requirement in the forms as below

Lets say I have 4 input fields.

<input type="text" formControlName="a1">
<input type="text" formControlName="a2">
<input type="text" formControlName="a3" value={{a1+a2}}>
<input type="text" formControlName="a4" value={{a1*a2}}>

here value is based on formula which may have any arithmetic expression example : (a1*a2)/a3

This form is dynamic data is coming from an api for example

const formData = [
  {
    id: "a1",
    type: 'text',
    value: '',
    formula: '',
  },
  {
    id: "a2",
    type: 'text',
    value: '',
    formula: '',
  },
  {
    id: "a3",
    type: 'text',
    value: '',
    formula: 'a1+a2',
  },
  {
    id: "a1",
    type: 'text',
    value: '',
    formula: 'a1*a2',
  },
];

please help me with this.enter image description here

T Naveen
  • 23
  • 3

2 Answers2

0

Subscribe to the valueChanges Observable to track changes in the desired inputs and use setValue to change the value of other inputs after each change. You should probably also change the input type to number to avoid worrying about converting strings to numbers.

Using a formula written as a string is an enitrely different problem. I think you should use String.replaceAll to apply the values to the formula and eval to calculate the result.

Working demo: https://stackblitz.com/edit/angular-zuy1ed

Code sample:

calculateResult(formValue: any, formulaName: "formula1" | "formula2") {
    let formula = this[formulaName];
    Object.keys(formValue).forEach(
        variable => (formula = formula.replaceAll(variable, formValue[variable]))
    );
    return eval(formula);
}

setupRecalculation() {
    this.form.valueChanges.subscribe(value => {
        value.a3 = this.calculateResult(value, "formula1");
        value.a4 = this.calculateResult(value, "formula2");
        this.form.controls.a3.setValue(value.a3, { emitEvent: false });
        this.form.controls.a4.setValue(value.a4, { emitEvent: false });
    });
}

Warning: By default, using setValue on a form control triggers the valueChanges event. To avoid an infinite loop, use { emitEvent: false } in the second argument of FormControl.setValue

Warning2: The API response you posted in your question seems to be vulnerable to a circular dependency of the variables (for example, a3 depending on a4, which depends on a2, which depends on a3 etc.). There should be a rule which ensures this is avoided: for example, a variable should depend only on the variables which come before it.

Wojciech K
  • 952
  • 7
  • 16
0

If values are fix, maybe you can try like this :

<!-- Better to use type="number" -->

<input type="number" formControlName="a1" (change)="calculate()">
<input type="number" formControlName="a2" (change)="calculate()">
<input type="number" formControlName="a3">
<input type="number" formControlName="a4">
calculate(): void {
  const { a1, a2 } = this.form.value;

  this.form.get('a3').setValue(a1 + a2);
  this.form.get('a4').setValue(a1 * a2);
}
Emilien
  • 2,701
  • 4
  • 15
  • 25