Reputation: 742
From Victor Savkin's post on Angular2 template syntax, shows how to use input and output property binding -
<todo-cmp [model]="todo" (complete)="onCompletingTodo(todo)"></todo-cmp>
@Component({selector: 'todo-cmp'})
class TodoCmp {
@Input() model;
@Output() complete = new EventEmitter(); // TypeScript supports initializing fields
}
The input property is decorated with @Input() while output property has @Output(). How should I declare a property which is going to have a 2 way property binding? Example: Assuming rootpanel component has 'suggestions' property (of type string) and searchPanel has 'getSuggestions property. Now I want the two properties to be bound to each other both ways. I tried -
rootpanel.html:
<search-panel [(getSuggestions)]="suggestions"> </search-panel>
But I am stuck while declaring the getSuggestions property in the searchPanel component.
Also what should be the type of the getSuggestions property - string or EventEmitter<string>
?
Please suggest.
Upvotes: 3
Views: 1271
Reputation: 60
The approach pixelbits recommended is exactly how you should do that, but if you have multiple two-way data binding properties on a component, or even one that changes frequently in your codebase, I created a decorator for that. If you are using npm here it is. Just go to the gihub page if you need the code.
With this, you can directly use:
import { Component } from '@angular/core';
import { TwoWay } from 'two-way-decorator';
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
styleUrls: ['./example.component.scss']
})
export class ExampleComponent {
@TwoWay()
public text: string;
@TwoWay()
public count: number;
}
Upvotes: 0
Reputation: 52837
If you want two-way model binding from the parent component:
[(model)]
You need the following in your child component:
@Input() model: string;
@Output() modelChange:EventEmitter<string>;
At some point when the model is overwritten in your child component, you'll emit the modelChange
event:
updateModel(newValue:string) {
this.model = newValue;
this.modelChange.emit(this.model);
}
From the parent component's perspective, [(model)]
is equivalent to:
[model]="model" (modelChange)="model=$event"
In this way, when the model property changes inside a child component, the change in the model propagates upwards though two-way binding, synching all the bound models along the way.
Upvotes: 4
Reputation: 657018
If you want to use [(getSuggestions)]
-style for two-way-binding declare the fields like
class TodoCmp {
@Input() getSuggestions;
@Output() getSuggestionsChange = new EventEmitter();
onClick() {
getSuggestions = 'someValue';
getSuggestionsChange.emit(getSuggestions);
}
}
getSuggestions
is probably not a good choice for such a input/output combination but it should demonstrate how they are connected. The output needs to have the same name as the input with an additional Change
.
If this naming scheme doesn't fit use your component like
<search-panel [suggestions]="suggestions" (getSuggestions)="updateSuggestions($event)> </search-panel>
with input/output like
class TodoCmp {
@Input() suggestions;
@Output() getSuggestions = new EventEmitter();
onClick() {
suggestions = 'someValue';
getSuggestions.emit(getSuggestions);
}
}
Upvotes: 2