Angular2 Component @Input two way binding

Steve Fitzsimons picture Steve Fitzsimons · Feb 2, 2017 · Viewed 37.9k times · Source

I have a data driven Angular application. I have a toggle component which I pass in a toggled state. My issue is that the two way data binding does not seem to work unless i pass in the toggle boolean as an object. Is there a way to get this to work without using an EventEmitter or passing the variable in as an object. This is to be a reusable component and the application is heavily data driven so passing the value in as an object in not an option. My code is....

toggle.html

<input type="checkbox" [(ngModel)]="toggled" [id]="toggleId" name="check"/>

toggle.component.ts

import { Component, Input, EventEmitter, Output } from '@angular/core';

@Component({
  moduleId: module.id,
  selector: 'toggle-switch',
  templateUrl: 'toggle-switch.component.html',
  styleUrls: ['toggle-switch.component.css']
})

export class ToggleSwitchComponent {

  @Input() toggleId: string;
  @Input() toggled: boolean;

}

parent.component.html

<toggle-switch toggleId="toggle-1" [(toggled)]="nongenericObject.toggled"></toggle-switch>

Answer

G&#252;nter Z&#246;chbauer picture Günter Zöchbauer · Feb 2, 2017

For [(toggled)]="..." to work you need

  @Input() toggled: boolean;
  @Output() toggledChange: EventEmitter<boolean> = new EventEmitter<boolean>();

  changeValue() {
    this.toggled = !(this.toggled); 
    this.toggledChange.emit(this.toggled);
  }

See also Two-way binding

[UPDATE] - 25 June 2019
From @Mitch's comment below:
It's worth noting that the @Output name must be the same as the @Input name, but with Change on the end. You can't call it onToggle or something. It's a syntax convention.