Accessing Other Components

@ViewChild and @ViewChildren

The @ViewChild and @ViewChildren decorators provide access to the instantiated class of child components, allowing you to interact with non-private fields programmatically.
The @ViewChild is a decorator function that takes the name of a component class as its input and finds its selector in the template of the containing component to bind to. @ViewChild can also be passed a template reference variable.
For example, we bind the class AlertComponent to its selector <app-alert> and assign it to the property alert. This allows us to gain access to class methods, like show().
1
import { Component, ViewChild } from '@angular/core';
2
import { AlertComponent } from './alert.component';
3
4
@Component({
5
selector: 'app-root',
6
template: `
7
<app-alert>My alert</app-alert>
8
<button (click)="showAlert()">Show Alert</button>`
9
})
10
export class AppComponent {
11
@ViewChild(AlertComponent) alert: AlertComponent;
12
13
showAlert() {
14
this.alert.show();
15
}
16
}
Copied!
In the interest of separation of concerns, we'd normally want to have child elements take care of their own behaviors and pass in an @Input(). However, it might be a useful construct in keeping things generic.
When there are multiple embedded components in the template, we can also use @ViewChildren. It collects a list of instances of the Alert component, stored in a QueryList object that behaves similar to an array.
1
import { Component, QueryList, ViewChildren } from '@angular/core';
2
import { AlertComponent } from './alert.component';
3
4
@Component({
5
selector: 'app-root',
6
template: `
7
<app-alert ok="Next" (close)="showAlert(2)">
8
Step 1: Learn angular
9
</app-alert>
10
<app-alert ok="Next" (close)="showAlert(3)">
11
Step 2: Love angular
12
</app-alert>
13
<app-alert ok="Close">
14
Step 3: Build app
15
</app-alert>
16
<button (click)="showAlert(1)">Show steps</button>`
17
})
18
export class AppComponent {
19
@ViewChildren(AlertComponent) alerts: QueryList<AlertComponent>;
20
alertsArr = [];
21
22
ngAfterViewInit() {
23
this.alertsArr = this.alerts.toArray();
24
}
25
26
showAlert(step) {
27
this.alertsArr[step - 1].show(); // step 1 is alert index 0
28
}
29
}
Copied!
As shown above, given a class type to @ViewChild and @ViewChildren a child component or a list of children component are selected respectively using their selector from the template. In addition both @ViewChild and @ViewChildren can be passed a selector string:
1
@Component({
2
selector: 'app-root',
3
template: `
4
<app-alert #first ok="Next" (close)="showAlert(2)">
5
Step 1: Learn angular
6
</app-alert>
7
<app-alert ok="Next" (close)="showAlert(3)">
8
Step 2: Love angular
9
</app-alert>
10
<app-alert ok="Close">
11
Step 3: Build app
12
</app-alert>
13
<button (click)="showAlert(1)">Show steps</button>`
14
})
15
export class AppComponent {
16
@ViewChild('first') alert: AlertComponent;
17
@ViewChildren(AlertComponent) alerts: QueryList<AlertComponent>;
18
// ...
19
}
Copied!
Note that view children will not be set until the ngAfterViewInit lifecycle hook is called.

@ContentChild and @ContentChildren

@ContentChild and @ContentChildren work the same way as the equivalent @ViewChild and @ViewChildren, however, the key difference is that @ContentChild and @ContentChildren select from the projected content within the component.
Again, note that content children will not be set until the ngAfterContentInit component lifecycle hook.
Last modified 3mo ago