DEV Community

Cover image for Exploring ViewChild Selectors
Hassam Ali
Hassam Ali

Posted on

Exploring ViewChild Selectors

ViewChild

ViewChild decorator is most commonly used to access the Child Component's instance and template. This is one the most common use cases. In this article we will be exploring several lesser known use cases.

ViewChild Selectors

The ViewChild has following selectors

  1. Any class with the @Component or @Directive decorator
  2. A template reference variable as a string (e.g. query with @ViewChild('cmp'))
  3. Any provider defined in the child component tree of the current component (e.g. @ViewChild(SomeService) someService: SomeService)
  4. Any provider defined through a string token (e.g. @ViewChild('someToken') someTokenVal: any)
  5. A TemplateRef (e.g. query with @ViewChild(TemplateRef) template;)

The 1, 2 and 5 are most commonly known and used. In this write up I will be exploring 3 and 4. So let's get started!

Accessing Child Component Provider Without Injecting.

Suppose you have a component called Parent component inside which there is another component called child. Child Component injects a service inside it called RandomNumberService which has method called getRandomNumber this method return a random number. This service is provided in Child's components decorator metadata

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css'],
  providers: [RandomNumberService],
})
Enter fullscreen mode Exit fullscreen mode

Service injected via this method is not singleton. For each instance of child component a new instance RandomNumberService will created. So if we want to access this service we will need to use ViewChild, lets see how we can use it.

export class ParentComponent implements OnInit {
  @ViewChild(RandomNumberService) randomNumberService: RandomNumberService;
  constructor() { }

  ngOnInit() {
  }

  ngAfterViewInit() {
    console.log(this.randomNumberService.number);
  }

}
Enter fullscreen mode Exit fullscreen mode

We can achieve the same result by accessing the child component's instance and then accessing the service but then we would have to make sure that the service instance variable is public otherwise it won't work so to avoid that we can use ViewChild with service.

Now lets take at point 4 which is

Accessing Any Provider Defined Through A String Token.

Moving forward with previous example suppose that inside child component you have provider defined in following way:

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css'],
  providers: [{provide: 'TokenName', useValue: 'Foo Bar'}],
})
Enter fullscreen mode Exit fullscreen mode

and now you need to access it. You can use the following format of ViewChild

export class ParentComponent implements OnInit {
  @ViewChild('TokenName') token: RandomNumberService;
  constructor() { }

  ngOnInit() {
  }

  ngAfterViewInit() {
    console.log(this.token); // logs 'Foo Bar'
  }
}
Enter fullscreen mode Exit fullscreen mode

Thats all for now!. Let me know how you use angular decorators and what are your favourite tips and tricks, and do let me know if missed anything.

Thanks for reading!
cover image credits: https://unsplash.com/photos/1seONCyPWfQ

Top comments (0)