Reputation: 149
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
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
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);
}
Upvotes: 4