How to use ViewChild in Angular 9
Tags: angular, directives, viewchild
Published: 2020-02-26 21:06:30

---
title: How to use ViewChild in Angular 9
published: true
description: ViewChild is a decorator and it's mostly used within angular when you need to select a particular element from the view.
tags: angular, directives, viewchild
---

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/m7cpz1au9gjxh4c9hjzm.png)

# How to use @ViewChild() in Angular 9

[Get right to the live example](https://stackblitz.com/edit/view-child-angular)
### What is @ViewChild() and when should we use it?

ViewChild is a decorator and it's mostly used within angular when you need to select a particular element from the view.

## Table of contents:
#### 1. Select a particular directive
#### 2. Select a particular HTML element
#### 3. Difference between ViewChild `{ static: false }` and `{ static: true }` 
#### 4. Using `read` to inject a different configuration object

<b style="color:red"> The following examples will use Angular 9, I say this because starting from version 9 you don't need to specify the second argument which defaults to false ({ static: false }), anything else remains the same.
</b>

## 1. Select a particular directive
```ts
@Directive({selector: 'child-directive'})
class ChildDirective {
  @Input() id! :number;
  ngAfterViewInit() {
    console.log("ngAfterViewInit child")
  }
}

@Component({
  selector: 'select-directive',
  template: `
    <child-directive id="1"></child-directive>
  `
})
class SelectDirectiveComponent implements OnInit, AfterViewInit {
  @ViewChild(ChildDirective) child!: ChildDirective;

  ngAfterViewInit() {
    console.log("ngAfterViewInit parent with child = ", this.child);
  }
}
```
As you might seen above it's pretty simple to select an html element from the view.

By using `@ViewChild(ChildDirective) child: ChildDirective;` we tell angular that we need to inject into our reference variable `child` the element from our view template with type ChildDirective.

By default angular will search for our `ChildDirective` after all the elements from our view have been created and the bindings have been initiated. Will see later, how to get the reference to our view before all the binding has been performed.

## 2. Select a particular element from view
```ts
@Component({
  selector: 'select-element',
  template: `
    <div #myDiv>
    </div>
  `
})
class SelectElementComponent implements AfterViewInit {
  @ViewChild('myDiv') child: HTMLElement;

  ngAfterViewInit() {
    console.log("ngAfterViewInit", this.child);
  }
}
```
Selecting an html element from view, it's pretty similar with selecting a directive, the main changes are with the aguments that we pass to our `@ViewChild` decorator.

Instead of using a type, we are going to specify the element that needs to be selected by using a string.

In our example above we are using `#myDiv` to identify our element in the view and `@ViewChild('myDiv')` to tell angular that we need to select that spcific element from our view.

## 3. Difference between ViewChild static false and static true properties

If you had a chance to look over [ViewChild decorator](https://angular.io/api/core/ViewChild) you might have seen that `@ViewChild` decorator accepts 2 arguments.

Now we are going to explore what ca we do if we are to use the second argument.

The second argument that ViewChild receives is an object which can have two properties
`static` and `read`. 

Let's talk first about the `static` option.
Before Angular 9, this `static` option had a value of true by default.

### What `{ static: true }` does?

Having `static` set to `true` will result in telling angular that we need to get the reference to that target element as soon as the component is created, however this means that we are going to get the reference 
<b style="color:red"> before our element had a chance to bind the inputs and init it's view.</b> 

#### Example
```ts
@Directive({selector: 'child-directive'})
class ChildDirective {
  @Input() id! :number;
  ngAfterViewInit() {
    console.log("child");
  }
}

@Component({
  selector: 'select-directive',
  template: `
    <child-directive id="1"></child-directive>
  `
})
class SelectDirectiveComponent implements AfterViewInit {
  @ViewChild(ChildDirective, { static: true}) child: ChildDirective;

  ngOnInit() {
    console.log("ngOnInit", this.child);
  }

  ngAfterViewInit() {
    console.log("ngAfterViewInit", this.child);
  }
}
```
Will print: 

`ngOnInit ChildDirective {}`

`ngAfterViewInit child`

`ngAfterViewInit ChildDirective {id: "1"}`

As you have seen, only after the child has it's view created we will see the data for our `ChildDirective` available in `ngAfterViewInit` from parent element.

### When should you use `{ static: true }` ?

One usecase could be, when you need to access a child element's instance fields that don't rely for their values on inputs from other elements.

#### Example: 
```ts
@Directive({selector: 'child-directive'})
class ChildDirective {
  @Input() id! :number;
  public childName = 'childName';
  ngAfterViewInit() {
    console.log("child ngAfterViewInit");
  }
}

@Component({
  selector: 'select-directive',
  template: `
    <child-directive id="1"></child-directive>
  `
})
class SelectDirectiveComponent implements AfterViewInit {
  @ViewChild(ChildDirective, { static: true}) child: ChildDirective;

  ngOnInit() {
    console.log("ngOnInit", this.child);
  }

  ngAfterViewInit() {
    console.log("ngAfterViewInit", this.child);
  }
}
```

So, `{ static: true }` only makes sense when you have a child that's using an instance field with a predefined value.

### What { static: false } does?
It means that angular is going to look for our target element only after the view has been created and in most of the cases this is the way you'll use it.

#### Example:
```ts
@Directive({selector: 'child-directive'})
class ChildDirective {
  @Input() id! :number;
  public childName = 'childName';
  ngAfterViewInit() {
    console.log("ngAfterViewInit child");
  }
}

@Component({
  selector: 'select-directive',
  template: `
    <child-directive id="1"></child-directive>
  `
})
class SelectDirectiveComponent implements AfterViewInit {
  @ViewChild(ChildDirective, { static: false}) child: ChildDirective;

  ngOnInit() {
    console.log("ngOnInit", this.child);
  }
  ngAfterViewInit() {
    console.log("ngAfterViewInit", this.child);
  }
}

```
Will output something like this:

`ngOnInit undefined`

`ngAfterViewInit child`

`ngAfterViewInit ChildDirective {childName: "childName", id: "1"}`

So, this is the most used approach and it will make angular look for our target element only after the view has been created. 
## 4. Using read to inject a different configuration object

```ts
export const TestInjectable = new InjectionToken<Inject>('someToken');

interface Inject {
  val: string;
}
@Directive({selector: 'child-directive',
providers: [{ 
    provide: TestInjectable, useValue: {val: 'someValue'}
  }]
})
class ChildDirective {
  @Input() id! :number;
  public childName = 'childName';
  ngAfterViewInit() {
    console.log("ngAfterViewInit child");
  }
}

@Component({
  selector: 'select-directive-read',
  template: `
    <child-directive id="1"></child-directive>
  `
})
class SelectDirectiveReadComponent implements AfterViewInit {
  @ViewChild(ChildDirective, { read: TestInjectable}) child: Inject;
  @ViewChild(ChildDirective, { read: ElementRef}) childTypeElementRef: ElementRef;
  @ViewChild(ChildDirective, { read: ChildDirective}) childTypeChildrenDirective: ChildDirective;

  ngAfterViewInit() {
    console.log("ngAfterViewInit", this.child);
    console.log("ngAfterViewInit", this.childTypeElementRef);
    console.log("ngAfterViewInit", this.childTypeChildrenDirective);
  }
}
```
<p>When you run this code, you'll see that:</p>

1. `this.childTypeElementRef` will have an instance of ElementRef
2. `this.child` will have an instance of TestInjectable 
3. `this.childTypeChildrenDirective` will have an instance of ChildDirective

### Why does all the the above code works?
Thanks to the read configuration parameter, we can specify for our ViewChild decorator that we need to inject a specific instance from the element that angular has queried for.

Using `InjectionToken` we provided a value of type `TestInjectable` for ChildDirective and this means we can use 
`@ViewChild(ChildDirective, { read: TestInjectable}) child: Inject;`
to get that specific instance from our `ChildDirective`.

For others instances like `ElementRef` and `ChildDirective` angular will perform the same checks.

### When should we use the `read` option?:
When we need to get an injectable instnace from a child element it's useful to use a ViewChild.

[Live example also available here](https://stackblitz.com/edit/view-child-angular)


<br>

### Stay tuned to get more tutorials on Web development
[Follow me on twitter](https://twitter.com/danielpdev)

Article first posted on [danielpdev.io](https://danielpdev.io)