Jun 26th, 2020 - written by Kimserey with .
Last week we looked into HostBinding
and HostListener
decorators and how they could be used. In this week post we continue on our discovery of great decorators by looking at ViewChild
and ViewChildren
. What the differences are, and when to use one or another.
ViewChild
ViewChild
is a decorator which when placed on a property, will execute a query on the view and assign the result to the property. It is tracked by the change detection hence is changed when the view changes.
The most common usecase is to use ViewChild
to get reference on a component displayed in the current view. For example if we have a HelloWorldComponent
which is in our page:
1
<app-hello-word></app-hello-world>
We can access it within our component with ViewChild
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Component({
selector: 'app-hello-world',
template: ''
})
export class AppHelloWorld {
message = 'Hello World';
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements AfterViewInit {
@ViewChild(AppHelloWorld) child: AppHelloWorld;
ngAfterViewInit(): void {
console.log(this.child.message);
}
}
As we can see the child
is available after the view has been initialised. Within our AppComponent
, we are able to get a reference of AppHelloWorld
by using its type directly in the decorator. Child view can be reference by type for components and directives.
Another way to use ViewChild
is to use a template reference.
1
<app-hello-word #helloworld></app-hello-world>
and reference it as such:
1
@ViewChild(AppHelloWorld) child: AppHelloWorld;
Lastly we can also directly reference TemplateRef
:
1
<ng-template let-message><ng-message>
1
@ViewChild(TemplateRef) template: TemplateRef<{ $implicit: string }>;
Lastly we are also able to get a reference on DOM elements using template reference
1
<div #test>Hello world</div>
and access it using ElementRef
1
@ViewChild(ElementRef) element: ElementRef;
ViewChildren
If we had two app-hello-world
components used on the view, ViewChild
would only return the first result. In order to access all matching children, Angular provides another decorator ViewChildren
.
If we modify our first example slightely and make use of the component twice
1
2
<app-hello-world [message]="'Hello world'"></app-hello-world>
<app-hello-world [message]="'Bye bye'"></app-hello-world>
with the following component
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Component({
selector: 'app-hello-world',
template: ''
})
export class AppHelloWorld {
@Input() message: string;
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements AfterViewInit {
@ViewChild(AppHelloWorld) child: AppHelloWorld;
ngAfterViewInit(): void {
console.log(this.child.message);
}
}
We would only see Hello world
printed in the console as ViewChild
only returns the first matching element. By making use of ViewChildren
, we are able to reference a list.
1
2
3
4
5
6
7
@ViewChildren(AppHelloWorld) children: QueryList<AppHelloWorld>;
ngAfterViewInit(): void {
this.children.forEach(c => {
console.log(c.message);
});
}
The QueryList
class is an enhanced iterable class provided by Angular as it keeps track of view changes but overal contains similar functionalities as array-like objects, map
, filter
, some
, find
, reduce
and forEach
.
Similarly as ViewChild
, it supports using template reference to reference components or DOM elements and it also supports getting the list of templates.
And that concludes today’s post!
In today’s post, we looked into ViewChild
and ViewChildren
. We saw how they could be used to get a reference on child elements used in the current template, and we saw how to access a list of them when components were used multiple times. I hope you liked this post and I see you on the next one!