EnlitenedZA
EnlitenedZA

Reputation: 149

Angular 2 Component with ngModel not updating parent model

I am trying to create a wrapper component for inputs such as a checkbox but I cannot get the parent (inputValue) variable to change, even though it is set as an ngModel.

This is my component definition:

@Component({
selector: 'my-checkbox',
inputs: ['inputValue', 'label'],    
template: `
    <div class="ui checkbox">
      <input type="checkbox" name="example" [(ngModel)]="inputValue" (change)="onChange($event)">
      <label>{{label}}</label>
    </div>`
})

export class CheckboxComponent {    

inputValue: boolean;

onChange(event) {
    this.inputValue = event.currentTarget.checked;
    console.log(this.inputValue);
}}

And I am using it like this in the parent view:

<my-checkbox [inputValue]="valueToUpdate" [label]="'Test Label'"></my-checkbox>

The console does log correctly and I can see that the internal (inputValue) is updating but not the external 'valueToUpdate' (the ngModel two-way binding is not updating correctly).

Upvotes: 3

Views: 6944

Answers (2)

Thierry Templier
Thierry Templier

Reputation: 202196

You need to define an output for your component and use the EventEmitter class to fire the corresponding event.

@Component({
  selector: 'my-checkbox',
  inputs: ['inputValue', 'label'],    
  outputs: ['inputValueChange']
  template: `
    <div class="ui checkbox">
      <input type="checkbox" name="example" [(ngModel)]="inputValue" (change)="onChange($event)">
      <label>{{label}}</label>
    </div>`
})
export class CheckboxComponent {    

  inputValue: boolean;
  inputValueChange: EventEmitter<any> = new EventEmitter();

  onChange(event) {
    this.inputValue = event.currentTarget.checked;
    console.log(this.inputValue);
    this.inputValueChange.emit(this.inputValue);
  }
}

This way you will be able to use two binding for your sub component:

<my-checkbox [(inputValue)]="valueToUpdate" [label]="'Test Label'">
</my-checkbox>

Upvotes: 6

Mark Rajcok
Mark Rajcok

Reputation: 364697

Follow @Thierry's answer (i.e., use an output property), but I suggest using the built-in ngModelChange event, rather than having two event bindings. I.e., having [(ngModel)] and (change) results in two event bindings, hence two event handlers run for each click. The built-in ngModelChange event is also a bit nicer/cleaner because $event is already mapped to the value of the checkbox, rather than the DOM click event. So, here are the suggested changes to @Thierry's answer:

<input type="checkbox" name="example" 
  [ngModel]="inputValue" (ngModelChange)="onChange($event)">


onChange(newValue) {
  this.inputValue = newValue;
  console.log(newValue);
  this.inputValueChange.emit(newValue);
}

Plunker

Upvotes: 4

Related Questions