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
Importing
ViewChild
: First, you need to importViewChild
from@angular/core
.import { Component, ViewChild } from '@angular/core';
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;
// ...
}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>
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 inngOnInit
, while{ static: false }
(default) accesses it inngAfterViewInit
.
Use Cases
- Interacting with Child Component Methods: Call methods or access properties of a child component.
- Manipulating DOM Elements: Directly interact with native elements, like focusing an input or reading its properties.
- 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 inngOnInit
.
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.