Modern Angular applications rely heavily on data binding, services, and components. But sometimes, you must directly access HTML elements or child components. That is where Template Reference Variables, ViewChild, and safe DOM manipulation come into play.
This article explains:
What Template Reference Variables are
How to use
ViewChildWhen (and when not) to manipulate the DOM
Real examples used in actual Angular projects
What Are Template Reference Variables?
Template Reference Variables (TRVs) allow you to get a direct reference to an HTML element or Angular component from the template.
You create a variable with the # symbol.
Example:
<input #usernameInput type="text">
<button (click)="save(usernameInput.value)">Save</button>
Here:
#usernameInputrefers to the<input>elementYou can pass its value directly into a method
TRVs with HTML Elements
Example: Accessing Input Value
<input #city type="text">
<button (click)="show(city.value)">Show</button>
Example: Access a DOM Element and Change Style
<p #para>Welcome to Angular</p>
<button (click)="highlight(para)">Highlight</button>
In the component:
highlight(el: HTMLElement) {
el.style.color = 'red';
}
TRVs with Child Components
You can also reference child components.
Parent Template:
<app-counter #counterRef></app-counter>
<button (click)="counterRef.increment()">Increment</button>
Child Component (Counter):
increment() { this.count++; }
This allows calling methods from the parent.
Using ViewChild for DOM Access in TypeScript
ViewChild is a decorator that helps you access:
HTML elements
Angular components
Directives
Template reference variables
From inside the TypeScript file.
Basic Syntax
@ViewChild('myInput') myInputElement!: ElementRef;
Template:
<input #myInput type="text">
Example: Accessing an Input Element
Template:
<input #emailInput type="text">
<button (click)="focusEmail()">Focus Input</button>
Component:
@ViewChild('emailInput') emailInput!: ElementRef;
focusEmail() {
this.emailInput.nativeElement.focus();
}
Example: Accessing a Child Component Using ViewChild
Child component:
export class TimerComponent {
start() { console.log('Timer started'); }
}
Parent template:
<app-timer></app-timer>
<button (click)="startTimer()">Start Timer</button>
Parent component:
@ViewChild(TimerComponent) timer!: TimerComponent;
startTimer() {
this.timer.start();
}
When Should You Use ViewChild?
Use ViewChild:
When you need to manipulate a specific DOM element
When you must call methods on a child component
When listening to custom component events is not enough
When you need to get initial sizes or layout values
When Should You Avoid ViewChild?
Avoid using ViewChild if:
You only need data binding (use
ngModel,@Input,@Output)You plan to rewrite everything using Angular animations
You want full control via RxJS and services
It causes too much coupling between components
Example: Auto-focus Input on Page Load
Template:
<input #username>
Component:
@ViewChild('username') username!: ElementRef;
ngAfterViewInit() {
this.username.nativeElement.focus();
}
Important:
Always use
ngAfterViewInit()The DOM will be available only after view initialization
Safety: Avoid Direct DOM Access When Possible
Angular runs in environments like:
Browser
Server (Angular Universal)
Web workers
Direct DOM access using nativeElement might break in some environments.
To handle this safely, Angular provides Renderer2.
DOM Manipulation Using Renderer2 (Recommended)
Renderer2 is the safe way to manipulate DOM elements.
Example:
constructor(private renderer: Renderer2) {}
@ViewChild('title') title!: ElementRef;
changeColor() {
this.renderer.setStyle(this.title.nativeElement, 'color', 'blue');
}
Template:
<h2 #title>Welcome</h2>
Renderer2 is platform-independent and recommended for long-term maintainability.
Case Study: Real-World Use of ViewChild
Scenario: You are building a data grid with a scrollable section. After filtering, you want to scroll back to the top.
Template:
<div class="table-container" #tableWrapper>
<!-- table rows --></div>
Component:
@ViewChild('tableWrapper') wrapper!: ElementRef;
scrollTop() {
this.wrapper.nativeElement.scrollTop = 0;
}
Call:
filterData() {
this.loadFilteredData();
this.scrollTop();
}
Useful in dashboards, reports, and admin panels.
Case Study: Call Method on a Child Component
Parent Template:
<app-product-list #productList></app-product-list>
<button (click)="refresh()">Refresh Products</button>
Child Component:
loadProducts() { /* API call */ }
Parent Component:
@ViewChild('productList') productList!: ProductListComponent;
refresh() {
this.productList.loadProducts();
}
This is useful for:
Reloading child tables
Resetting forms
Triggering calculations
Summary
| Concept | Purpose | Use Case |
|---|---|---|
| Template Reference Variable | Access element/component from template | Pass input value, call child functions |
| ViewChild | Access element/component from TypeScript | Focus input, call methods, control DOM |
| Renderer2 | Safe DOM manipulation | Styling, classes, attributes |
Conclusion
Angular provides safe and structured ways to access elements, components, and DOM properties.
Using Template Reference Variables and ViewChild correctly helps you:
Control DOM when needed
Reduce complex event passing
Access child components
Create smooth user experiences
Mastering these concepts is essential for building interactive, professional Angular applications.

Join the conversation! Your thoughts help the community grow.