Thursday, July 29, 2021

Angular @ViewChild Decorator With Examples

@ViewChild decorator in Angular is used if you want to access any directive, child component or DOM element in the Component class.

Using @ViewChild decorator you can configure a view query, that is done by passing a selector with @ViewChild. For example

@ViewChild('membershipForm') memberForm

Here ‘membershipForm’ is the passed selector.

The change detector looks for the first element or the directive matching the selector in the view DOM and assigns it to the property decorated with @ViewChild.

View queries and ngAfterViewInit callback

View queries are set before the ngAfterViewInit callback is called. That means ngAfterViewInit callback is the best place to manipulate the element or directive by using the reference variable.

ViewChild Metadata Properties

You can pass the following three metadata properties with @ViewChild decorator.

  • selector- The directive type or the name that has to be queried.
  • read- Used to read a different token from the queried elements.
  • static- True to resolve query results before change detection runs, false to resolve after change detection. Defaults to false.

read and static properties are optional.

@ViewChild decorator Angular examples

1. Using ViewChild with custom directive. In the example there is a custom attribute directive that sets the background color for the element where it is used.

import { Directive, ElementRef, Renderer2 } from '@angular/core';

@Directive({
  selector: '[appCustomdirective]'
})
export class CustomdirectiveDirective {
  defaultColor: string = 'yellow';
  constructor(private el: ElementRef, private renderer: Renderer2) { 
    this.highLight(this.defaultColor);
  }

  private highLight(color : string){
    this.renderer.setStyle(this.el.nativeElement,'backgroundColor',color);
  }
}

We’ll use this directive in the app.component.html

<p>Highlighting is done using a <span appCustomdirective>custom directive</span></p>
<p [style.background-color]="color">Highlight in different color</p>

As you can see there is also a style binding where style.background-color is bound to the “color” property. Now, to set this color property suppose you want to check the defaultColor property of the directive and set color accordingly. For that we need to access the directive in the Component class and thats where we can use @ViewChild.

app.component.ts

import { Component, ViewChild } from '@angular/core';
import { CustomdirectiveDirective } from './directives/customdirective.directive';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent{

  color: string='yellow';
  @ViewChild(CustomdirectiveDirective)
  set highLightColor(directive: CustomdirectiveDirective) {
    console.log('In Setter')
    if(directive.defaultColor === 'yellow'){
      this.color = 'red';
    }
  };
}

Here setter is used to set the value of color property after checking the defaultColor property of the directive.

2. Using ViewChild to access the child component. In the example there is a component with one method and we want to access that method from the parent component.

highlight.component.ts

import { Component } from "@angular/core";

@Component({
  selector: 'app-highlight',
  templateUrl: './highlight.component.html'
})
export class HighlightComponent{
  getHighlightColor(){
    return 'red';
  }
}

highlight.component.html

<p>Test Content</p>

In the parent component using @ViewChild we can get a reference to the child component and then execute the getHighlightColor() of the component.

app.component.ts

import { AfterViewInit, Component, ViewChild } from '@angular/core';
import { HighlightComponent } from './hello-world/highlight.component';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit{
  color: string;
  @ViewChild(HighlightComponent) hlComponent: HighlightComponent;
 
  ngAfterViewInit(): void {
    console.log(this.hlComponent.getHighlightColor());
    this.color = this.hlComponent.getHighlightColor();
  }
}

app.component.html

<app-highlight [style.color]="color"></app-highlight>

Note that the above example will throw ExpressionChangedAfterItHasBeenCheckedError as the expression value has been changed after change detection has completed.

3. Accessing DOM elements having template reference variable. That is a good use case where using @ViewChild decorator makes a lot of sense. For example we’ll create a template driven form with a reference to the form. That template reference is then used with the @ViewChild so that you can get access to the form object in your type script code.

template-driven.component.html

<div class="container">
  <div class="row">
    <div class="col-xs-12 col-sm-10 col-md-8">
      <h1>Membership Form</h1>
      <form (ngSubmit)="onSubmit()" #membershipForm="ngForm">
        <div class="form-group">
          <label for="name">Name</label>
          <input type="text" class="form-control" 
            id="name"
            ngModel name="name">                        
        </div>
        <div class="form-group">
          <label for="email">email</label>
          <input type="email" class="form-control" 
            id="email"
            ngModel name="email">                        
        </div>
        <div class="form-group">
          <label for="mdate">Membership Date</label>
          <input type="date" class="form-control" id="mdate"
            [ngModel]="currentDate | date:'yyyy-MM-dd'"  name="mdate">                        
        </div>
        <div class="form-group">
          <label for="type">Membership Type</label>
          <select class="form-control" id="type"                    
              ngModel name="type">
            <option *ngFor="let mtype of membershiptypes" [value]="mtype">{{mtype}}</option>
          </select>
        </div>
        <button type="submit" class="btn btn-success">Submit</button>
      </form> 
    </div>
  </div>
  <hr>
  <div *ngIf="submitted">
    <div class="row">
      <div class="col-xs-12 col-sm-10 col-md-8">
        <p>Name: {{member.name}}</p>
        <p>email: {{member.mail}}</p>
        <p>Membership Date: {{member.membershipDate | date:'dd/MM/yyyy'}}</p>
        <p>Membership Type: {{member.membershipType}}</p>
      </div>
    </div>
  </div>  
</div>

template-driven.component.ts

import { Component, ViewChild } from "@angular/core";
import { NgForm } from "@angular/forms";
import { Member } from "./member.model";

@Component({
  selector: 'app-tempdriven',
  templateUrl: './template-driven-validation.component.html'
})
export class TemplateDrivenFormComponent{
  @ViewChild('membershipForm') memberForm : NgForm;
  membershiptypes = ['Silver', 'Gold', 'Platinum'];
  currentDate = new Date();
  member = new Member('', '', new Date(), '');
  submitted = false;

  onSubmit(){
    this.submitted = true;
    this.member.name = this.memberForm.value.name;
    this.member.mail = this.memberForm.value.email;
    this.member.membershipDate = this.memberForm.value.mdate;
    this.member.membershipType = this.memberForm.value.type; 
  }
}

That's all for this topic Angular @ViewChild Decorator With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Angular @ViewChildren Decorator With Examples
  2. Angular @HostListener Decorator With Examples
  3. Angular @HostBinding Decorator With Examples
  4. NgNonBindable Directive in Angular
  5. How to Create a Custom Structural Directive in Angular

You may also like-

  1. Navigate to a Route Programmatically in Angular
  2. Angular Two-Way Data Binding With Examples
  3. How to Add Bootstrap to Angular Application
  4. FormBuilder in Angular Example
  5. How HashMap Works Internally in Java
  6. How to Run a Shell Script From Java Program
  7. Python Program to Check Armstrong Number
  8. Spring MVC PDF Generation Example

No comments:

Post a Comment