Skip to main content

ViewChild Decorator

The @ViewChild decorator in Angular is a key feature used in component classes to access a child component, directive, or a DOM element directly from the template. This decorator provides a way to interact with child components and elements dynamically and programmatically.

Basic Concept

@ViewChild allows a parent component to:

  • Access methods and properties of a child component.
  • Interact with native elements or directives.
  • Manipulate child components or elements after they are fully initialized.

How to Use @ViewChild

  1. Importing ViewChild: First, you need to import ViewChild from @angular/core.

    import { Component, ViewChild } from '@angular/core';
  2. Using ViewChild in Component Class: Use the decorator to bind a local variable in the template to a property in the component class.

    @Component({/* ... */})
    export class AppComponent {
    @ViewChild('childRef') childComponent: ChildComponent;

    // ...
    }
  3. Accessing the Child in the Template: In your template, assign a template reference variable to the child component or element.

    <app-child #childRef></app-child>
  4. Accessing Child Properties and Methods: Once the view is initialized, you can access properties and methods of the child component from the parent component.

Accessing Native Elements

  • @ViewChild can also be used to access native DOM elements. In this case, you use it with a template reference variable and ElementRef.

    <input #inputRef type="text">
    @ViewChild('inputRef') inputElement: ElementRef;

    ngAfterViewInit() {
    this.inputElement.nativeElement.focus(); // Example action
    }

More Examples

Here are additional examples to illustrate its various uses:

Example 1: Accessing a Child Component's Method

Suppose you have a child component with a method that you want to call from the parent component.

Child Component (child.component.ts):

@Component({
selector: 'app-child',
template: `<p>Child component</p>`
})
export class ChildComponent {
greet() {
alert('Hello from the Child Component!');
}
}

Parent Component:

@Component({
selector: 'app-parent',
template: `<app-child #childRef></app-child>
<button (click)="onButtonClick()">Call Child Method</button>`
})
export class ParentComponent {
@ViewChild('childRef') childComponent: ChildComponent;

onButtonClick() {
this.childComponent.greet();
}
}

In this example, the parent component calls the greet method of the child component when a button is clicked.

Example 2: Interacting with a DOM Element

If you want to directly interact with a DOM element, such as focusing an input field:

Parent Component Template:

<input #inputRef type="text">
<button (click)="focusInput()">Focus Input</button>

Parent Component Class:

@Component({/* ... */})
export class AppComponent {
@ViewChild('inputRef') inputElement: ElementRef;

focusInput() {
this.inputElement.nativeElement.focus();
}
}

Here, clicking the button will focus the input field using a direct reference to the native DOM element.

Example 3: Using ViewChild with a Directive

Suppose you have a directive applied to an element and you want to access its instance:

Directive:

@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
highlight(color: string) {
// highlight logic
}
}

Parent Component:

<p appHighlight #highlightRef="appHighlight">Text to be highlighted</p>
<button (click)="highlightText()">Highlight Text</button>
@Component({/* ... */})
export class AppComponent {
@ViewChild('highlightRef') highlightDirective: HighlightDirective;

highlightText() {
this.highlightDirective.highlight('yellow');
}
}

In this example, the highlightText method in the parent component will call the highlight method of the HighlightDirective instance.

Example 4: Dynamic ViewChild

Sometimes you need to access a ViewChild based on a condition or dynamically:

Parent Component:

<div *ngIf="shouldShowChild">
<app-child #dynamicChildRef></app-child>
</div>
@Component({/* ... */})
export class AppComponent {
@ViewChild('dynamicChildRef', { static: false }) dynamicChildComponent: ChildComponent;
shouldShowChild = false;

ngAfterViewInit() {
// Access dynamicChildComponent after it's rendered
}
}

In this example, dynamicChildComponent is only accessible in ngAfterViewInit since it's rendered conditionally.

Dynamic Querying

  • @ViewChild also accepts a second argument, an object for dynamic querying. For example, { static: true } is used to access the element in ngOnInit, while { static: false } (default) accesses it in ngAfterViewInit.

Use Cases

  1. Interacting with Child Component Methods: Call methods or access properties of a child component.
  2. Manipulating DOM Elements: Directly interact with native elements, like focusing an input or reading its properties.
  3. Working with Directives: Interact with directives applied to elements in the template.

Best Practices

  • Use Responsibly: Direct DOM manipulation or tight coupling with child components can lead to less maintainable code. Prefer data-binding and event-based communication where possible.
  • Lifecycle Hooks: Remember that elements and components are available in the ngAfterViewInit lifecycle hook, not in ngOnInit.

Conclusion

@ViewChild is a powerful feature in Angular that provides direct access to components, directives, and DOM elements. It enables a wide range of interactions and manipulations that are essential for dynamic and responsive applications. Understanding how to use @ViewChild effectively is crucial for advanced Angular development.