Check out our Angular Book Series.

How do I use a set method to access an conditionally created ViewChild in Angular?

In last week's post I spoke about the problems accessing an Angular ViewChild if it is conditionally created using *ngIf. The solution I proposed there was to use the hidden directive instead of *ngIf. This works, but the caveat is that the child is always created as part of the DOM even if it is not always displayed. I wanted to do another post, providing a different approach

The Setup

I'm going to modify the same application I built last time. It was a simple application created with the Angular CLI and I added one child component. You can get the full code here.

Creating the View

This time, I'm adding a third sample to the app.component.html template:


<button (click)="child3Hidden = !child3Hidden">Toggle Sample 3 Visibility</button>
<br/>
Value Passed into Child: <input type="text" (keyup)="onSample3Change($event)" />
<br/>
<app-view1 #child3 *ngIf="!child3Hidden" ></app-view1>

It uses a value, child3Hidden, to toggle the visibility of the child. Create that in app.component.ts:


child3Hidden = true;

There is an input which is used to change the input value for our app-view1 component:


onSample3Change(event) {
this.child3.value = event.currentTarget.value;
}

This just takes the text input from the AppComponent view and passes it to the ViewChildReference. This is all a similar setup to what we've seen before.

The Problem

Since this ViewChild is conditionally created with *ngIf we cannot access it inside the ngOnInit() and will get an error. The ngOnInit() is like this:


ngOnInit() {
console.log(this.child3);
}

You'll see something like this:

Just an error because the default state of the ViewChild is undefined.

A Solution

Instead of trying to access the ViewChild inside of ngOnInit() we can define the child using get and set methods, like this:


@ViewChild('child3')
set child3(value: View1Component) {
this._child3 = value;
console.log(this.child3);
}
get child3(): View1Component {
return this._child3;
}

Whatever code we want to run in ngOnInit() can be run in the set method, which will get toggled every time the child is created or destroyed. I clicked the button a bunch of times to show you the output:

It is an alternate solution, which works pretty well. The trick part is that whenever you access the ViewChild you'll have to do an undefined check with this approach, something you would not have to do if it were hidden.

Get can get the full code here.

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
All Content Copyright 2005, 2006, 2007, 2008, 2009 Jeffry Houser. May not be reused without permission
BlogCFC was created by Raymond Camden. This blog is running version 5.9.2.002.