Components can communicate with each other in a loosely coupled manner. There are various ways Angular's components can share data, including the following:
- Passing data from parent to child using @Input()
- Passing data from child to parent using @Output()
- Using services for data sharing
- Calling ViewChild, ViewChildren, ContentChild, and ContentChildren
- Interacting with the child component using a local variable
We will only describe the first three ways. A component can declare input and output properties. To pass the data from a parent to a child component, the parent binds the values to the input properties of the child. The child's input property should be decorated with @Input(). Let's create TodoChildComponent:
@Component({
selector: 'todo-child',
template: `<h2>{{todo.title}}</h2>`
})
export class TodoChildComponent {
@Input() todo: Todo;
}
Now, the parent component can use todo-child in its template and bind the parent's todo object to the child's todo property. The child's property is exposed as usual in square brackets:
<todo-child [todo]="todo"></todo-child>
If a component needs to pass the data to its parent, it emits custom events via the output property. The parent can create a listener to a particular component's event. Let's see that in action. The child component ConfirmationChildComponent exposes an EventEmitter property decorated with @Output() to emit events when the user clicks on buttons:
@Component({
selector: 'confirmation-child',
template: `
<button (click)="accept(true)">Ok</button>
<button (click)="accept(false)">Cancel</button>
`
})
export class ConfirmationChildComponent {
@Output() onAccept = new EventEmitter<boolean>();
accept(accepted: boolean) {
this.onAccept.emit(accepted);
}
}
The parent subscribes an event handler to that event property and reacts to the emitted event:
@Component({
selector: 'confirmation-parent',
template: `
Accepted: {{accepted}}
<confirmation-child (onAccept)="onAccept($event)"></confirmation-child>
`
})
export class ConfirmationParentComponent {
accepted: boolean = false;
onAccept(accepted: boolean) {
this.accepted = accepted;
}
}