Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

angular2 checkbox formcontrol

For a simple checkbox with a string value bound to a FormControl:

export class CheckboxComponent {
  formControl: FormControl;
  option: {value: string};

  constructor() {
    this.formControl = new FormControl(); 
    this.option = {value: "MyValue"};

         this.formControl.valueChanges.subscribe(console.log);
  }

}
<input type="checkbox" [formControl]="formControl" [value]="option.value" name="SomeName" />

The output of the subscribe is true, false, true, false.... I want the angular 2 to bind the string value "MyValue" in the FormControl.

By default angular 2, FormControl and checkboxes seem to bind boolean values which is strange since default browser submit behaviour is to send the value of the checkbox and, in the case of multiple checkboxes with the same name, an array of checkbox values bound to the name of the checkboxes.

Would be pretty useless to submit:

Items=[true, false, true, true, true, false]

Instead of:

Items=[Toothbrush, Floss, Glock, Clean underwear]

So in essence: How to make angular 2 bind the string value not the boolean value?

Kind regards,

like image 479
Innovating Concepts Avatar asked Oct 13 '16 11:10

Innovating Concepts


1 Answers

I believe I solved your (and my) issue by utilizing a custom directive that "overrides" the default CheckboxControlValueAccessor. Angular2 core sets the onChange event to fire whether the box is checked or not. The code below fires an object with the whether it's checked and the value. You will just need to set the html element as an input of type checkbox, and attached the value you want to track with [value]={valueToTrack}

import {Directive, ElementRef, Renderer, forwardRef} from '@angular/core';

import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';


export const CHECKBOX_VALUE_OVERRIDE_ACCESSOR: any = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => CheckboxControlValueOverrideAccessor),
  multi: true,
};

@Directive({
  selector: 'input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]',
  host: {'(change)': 'onChange({checked: $event.target.checked, value: $event.target.value})', '(blur)': 'onTouched()'},
  providers: [CHECKBOX_VALUE_OVERRIDE_ACCESSOR]
})

export class CheckboxControlValueOverrideAccessor implements ControlValueAccessor {
  onChange = (_: any) => {};
  onTouched = () => {};

  constructor(private _renderer: Renderer, private _elementRef: ElementRef) {}

  writeValue(value: any): void {
    this._renderer.setElementProperty(this._elementRef.nativeElement, 'checked', value.checked);
  }
  registerOnChange(fn: (_: any) => {}): void { this.onChange = fn; }
  registerOnTouched(fn: () => {}): void { this.onTouched = fn; }

  setDisabledState(isDisabled: boolean): void {
    this._renderer.setElementProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
  }
}
like image 166
Austin Shoecraft Avatar answered Sep 27 '22 20:09

Austin Shoecraft