I have created a component that is meant to be a switch. You would use it much the same as you would a checkbox. This is a stripped down version.
my-switch.component.ts:
import {Component, Input, Output, EventEmitter} from '@angular/core';
@Component({
selector: 'my-switch',
template: `<a (click)='toggle()'>
<span *ngIf='value'>{{onText}}</span>
<span *ngIf='!value'>{{offText}}</span>
</a>`
})
export class MySwitchComponent {
@Input() onText: string = 'On';
@Input() offText: string = 'Off';
@Input() value: boolean;
@Output() change = new EventEmitter <boolean> ();
position: string;
toggle() {
this.value = !this.value;
this.change.emit(this.value);
}
}
My plan is to use it like this:
parent-component.ts
import {Component} from '@angular/core';
import {MySwitchComponent} from 'my-switch.component';
@Component({
selector: 'my-sites',
directives: [MySwitchComponent]
template: `<table>
<tr *ngFor='let item of items'>
<td>
<my-switch
[(value)]='item.options.option1'
(change)='logItem(item)'>
</my-switch>
</td>
</tr>
</table>`
})
export class MySitesComponent {
items: Object[] = [
{options: { option1: false }}
];
logItem(item) {
console.log(item)
}
}
Again, this is simplified, but I think illustrates what I expect. My expectation is that when the switch is clicked, the view updates from "Off" to "On" and the value of the option is logged. The problem is that the value that is logged looks like this:
{options: {option1: false}}
My belief is that the items being iterated over are read-only. I know that I can work around this issue, but I would like to know if what I am trying to do is possible, or ill-advised, and also why it doesn't work.
Angular "de-sugars" the
[(x)]
syntax into anx
input property for property binding and anxChange
output property for event binding. -- reference
Therefore, if you name your input property value
, you must name your output property valueChange
:
@Output() valueChange = new EventEmitter <boolean> ();
That's the only piece of the puzzle you were missing. You now have two-way databinding between a parent and a child component.
If you want to execute some logic when the child changes/emit()
s the value, catch the (valueChange)
event in the parent component:
(valueChange)='logItem(item)'>
Plunker
I also suggest
console.log(JSON.stringify(item))
In parent child scenario you can take advantage of two-way binding with xxxChange Output property
as shown below, ,
In Parent - [(xxx)]="someValue"
In Child - @Input xxx: boolean;
@Output() xxxChange = new EventEmitter <boolean> ();
Note that xxxChange
property. which is missing in your case
Now, Look here for the code- Plunker
<td> From Parent - {{item.options.option1}} <--------------------value will keep changing
<my-switch
[(value)]='item.options.option1'> <---------two way binding
</my-switch>
</td>
Note here, [()]
represents two way binding so in parent you don't need to use (valueChange)="someValue=$event"
to catch the change. [(value)]='item.options.option1'
will automatically bind you new or changed value to item.options.option1
.
export class MySwitchComponent {
@Input() value: boolean;
@Output() valueChange = new EventEmitter <boolean> (); <----xxxChange output property
...
...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With