Search code examples
angulartypescriptangular-servicesautofillngx-formly

ngx-formly autofill one of three fields if two are already defined



i built three fields with formly. Together they can have a max of 100%.
What ist best way to autofill one of the fields, if two have a value.
For Example:

First field: 30
Second field: 20
Then the third field should automatically filled with: 50

What ist the "best" solution for this?

I already found a almost working way but iam sure my solution is not the goto. I used the formly lifecycle hooks to get and send the current value of my three fields to a service and calculate the value for my last field in there. The problem was that it generated a lot of traffic and slowed down my application. If i tried to write my own number into the last field, the input got instantly overwrote by the value which the service returned. I want the user to be able to overwrite the autofilled field and autoclear the other fields

My approach:

The hook in my third formly field which checks if two fields are filled:

hooks: {
    doCheck: (field: FormlyFieldConfig) => {
        let fields = field.form.getRawValue();

        if ( 
            fields.fieldOne.value !== null && 
            fields.fieldTwo.value !== null &&
            fields.fieldThree.value  !== calculateFieldsService.calculateFieldThree(
                fields.fieldOne,
                fields.fieldTwo
            )
        ) {
            fields.fieldThree.value = calculateFieldsService.calculateFieldThree(
                fields.fieldOne,
                fields.fieldTwo
            )   
            field.form.setValue({...fields, ...fields} );
        }
    }
}

The service which should calculate my field value if two fields are filled:

@Injectable({
  providedIn: 'root'
})
export class CalculateFieldsService { 

  calculateFieldThree(fieldOne, fieldTwo): number {
    if (fieldOne.value >= 0 && fieldTwo.value >= 0) {
      let fieldValue = 100 - (fieldOne.value + fieldTwo.value);    
      return fieldValue < 0 ? 0 : fieldValue;
    }
    return null;
  }
}

Solution

  • IMO doCheck is not the right way, with formly there are two ways that to autofill a field:

    expressionProperties: {
      'model.c': (m) => {
        return m.a && m.b ? (m.a + m.b) : null;
      }
    }
    
    • subscribe to form.valueChanges