Angular2 Component @Input two way binding

AngularTypescriptData BindingComponentsDecorator

Angular Problem Overview


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>

Angular Solutions


Solution 1 - Angular

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.

Solution 2 - Angular

Although the question has more than 2 years old I want to contribute my 5 cents...

It isn't a problem about Angular, its about how Javascript works... Simple variables (number, string, boolean, etc) are passed by value whereas complex ones (objects, arrays) are passed by reference:

You can read more about this in Kyle Simpson´s series You dont know js:

https://github.com/getify/You-Dont-Know-JS/blob/master/types%20%26%20grammar/ch2.md#value-vs-reference

So, you can use an @Input() object variable to share scope between components without need to use emitters, observers and whatever similar.

// In toggle component you define your Input as an config object
@Input() vm: Object = {};

// In the Component that uses toggle componet you pass an object where you define all needed needed variables as properties from that object:
config: Object = {
    model: 'whateverValue',
    id: 'whateverId'
};

<input type="checkbox" [vm]="config" name="check"/>

This way you can modify all object properties and you get same value in both components because they share same reference.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSteve FitzsimonsView Question on Stackoverflow
Solution 1 - AngularGünter ZöchbauerView Answer on Stackoverflow
Solution 2 - AngularLorraineView Answer on Stackoverflow