2

I have a form model with some indicators that are represented as checkboxes. Currently they model their value as true/false in the form object json. What I would like is for their value to convert from a boolean to a number, 1/0 respectively. Is there a smart way to do this?

Example code:

@Component

template: `
     <form [formGroup]="myForm" (ngSubmit)="save(myForm.value)">
         <input type="checkbox" id="myToggle" formControlName="myToggle"/>
     </form>
`
export class MyComponent implementes OnInit{
private myForm:FormGroup;
myToggle: number;

constructor(private _fb:FormBuilder) {}

ngOnInit() {
    this.myForm = this._fb.group({
      myToggle: [0]
    });
}

Hopefully the above is demonstrating that I'm trying to set the type of "myToggle" to a number. Initializing the form is setting the default to 0 and correctly leaving the checkbox unchecked. However, updating the checkbox to checked will set the form value to true instead of 1. I want it to be updated to 1. Via this question I see that there are some options for converting booleans to numbers. However, I'm unsure of exactly how to implement this with the reactive form model.

Community
  • 1
  • 1
Jacob Kochocki
  • 240
  • 1
  • 5
  • 13

1 Answers1

1

FormControl has registerOnChange method, which allows you to specify a callback executed after every change.

Having your example you can access control let ctrl = this.myForm.controls["myToggle"] (I'd prefer create this manually) and then you can do sth like ctrl.registerOnChange(() => ctrl.patchValue(ctrl.value ? 1 : 0));.

mat3e
  • 791
  • 5
  • 16
  • Is there no way to use this in the form init? Where I'm defining formGroups, formArrays, etc.? In the case where I have thirty true/false indicator fields, this seems like a lot of extra code to do something that ought to be trivial. – Jacob Kochocki Nov 18 '16 at 16:46
  • It's non-trivial because the actual underlying HTML specifies the checkbox checked value is a boolean. https://www.w3.org/wiki/HTML/Elements/input/checkbox Sounds like you can loop over your controls by, say, name (`name.indexOf("chk") !== -1`) and apply the function over and over. – silentsod Nov 18 '16 at 17:14
  • You should create your own function `createNumberCheckbox(formState?: any, validator?: ValidatorFn|ValidatorFn[], asyncValidator?: AsyncValidatorFn|AsyncValidatorFn[]): FormControl {let result=new FormControl(formState,validator,asyncValidator); result.registerOnChange/*stuff from my answer*/; return result}` and then use it. Like `myToggle: createNumberCheckbox(0)` inside init or wherever. – mat3e Nov 18 '16 at 22:58
  • @Mate it sets the value to bit but once the checkbox is clicked again it returns to boolean – moodygeek May 19 '17 at 00:04
  • @Gbenro'Skenzy'Selere - at the end I took a different approach in my own lib (https://github.com/mat3e/dorf/tree/master/src/fields). You can verify `DorfCheckboxComponent` code. In the HTML there is a secret field which stores the value: `` and it keeps a proper type and there is an ordinary checkbox, identified as `#view` as well. – mat3e May 19 '17 at 17:07