Viewchild Decorator Angular Angular

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!

Conclusion

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!

External Source

Designed, built and maintained by Kimserey Lam.