Directives In Angular
By the end of this blog, we’ll learn:
What are Angular Directives?
The need for Angular Directives.
Problems without Angular Directives.
Types of Angular Directives.
Why are custom directives required?
How to build custom directives with real-time use cases?
How do directives work internally?
Alternatives and the future of Angular Directives.
What Are Angular Directives?
Before jumping into Angular directives, let’s imagine a static web page.
Such a page would just be static DOM content — plain HTML with fixed text, images, or links. This is fine for static websites, like a simple blog, where the content rarely changes for different users.
But modern applications are rarely static.
We need dynamic content — content that changes depending on time, context, or user.
For example:
A banking website shows different account details for User A and User B.
The same site, when accessed by a bank employee, displays customer records.
A manager might even see both employee activity and customer data on the same site.
This flexibility — serving different views of the same application to different users — is what makes a site dynamic.
And this is exactly where Angular Directives come into play: they help us control and extend the DOM dynamically, making HTML interactive and adaptable.
But we still don’t have a crystal-clear picture of why Angular Directives are needed. Let’s build one.
Suppose you develop a component called CustomerDetails with:
customer.htmlcustomer.tscustomer.csscustomer.spec.ts
And customer.html has two main parts:
Customer details table
Update customer details form
Now here’s the requirement:
Managers should be able to update customer details.
Back-office users should only be able to view details and pass them to managers for updates (e.g., approving/rejecting a loan).
At this point, we have two options:
Build a separate website just for managers.
Use the same website, but restrict certain users from seeing the update form or performing update actions.
Clearly, option 2 is more efficient — and this is exactly where Angular Directives help us control the DOM based on logic, such as user roles.
So let’s move ahead with Option 2. But even here, we again face two choices:
Show the update form to all back-office users, but block them from submitting (showing an error when they try).
- Not a good user experience. It’s like inviting someone to dinner but refusing to serve them food.
Hide the update form entirely for other back-office users, and show it only to managers.
- A cleaner and more user-friendly approach.
Now comes the real question:
We have all the content on the same page. How do we conditionally show/hide certain sections of the DOM, based on user roles?
Think about it — isn’t this a problem worth solving?
This is exactly where Angular Directives step in.
They give us the power to control the DOM dynamically — not just for role-based access, but for many other scenarios too.
And in this blog, we’ll explore:
How Angular directives solve such problems.
The different types of directives.
Why and how to build custom directives for real-world case
So, before we continue our discussion, let's first make our definition very clear and simple.
And now we can answer the question: What Are Angular Directives?
What Are Angular Directives?
Angular Directives are one of the most powerful features of Angular. They are special instructions that allow us to control and manipulate the DOM dynamically.
Think of them as commands that tell Angular how a part of the page should behave, appear, or even whether it should exist at all or not.
In simple terms:
A directive is a set of instructions executed by Angular to decide how a particular DOM element should be created, displayed, styled, or updated.
These instructions are completely under the developer’s control, which means we can dynamically change the DOM based on data, conditions, or user roles.
And remember:
Controlling the DOM doesn’t only mean showing and hiding elements.
Depending on the type of directive, we can also change an element’s structure, appearance, or behavior.
Now, we’ll explore the types of Angular Directives with real-world use cases, so we can clearly see how they solve practical problems.
Types of Angular directives:
So far we’ve covered why directives are needed and what they are.
Now let’s get technical and look at the three main types of Angular directives — each serves a different purpose in controlling the DOM:Component directives
The most common form of directive. A component combines a template, styles, and behavior. Think of it as a reusable UI unit (e.g.,<customer-details>).Structural directives
These change the DOM structure by adding or removing elements. Examples:*ngIf,*ngFor. Use them when you want to show, repeat, or remove parts of the page based on data or conditions.Attribute directives
These change the appearance or behavior of an existing element without altering its structure. Examples:ngClass,ngStyleor a custom directive that toggles validation or role-based attributes.
Below, we’ll dive into each type deeply — with practical use-cases, code snippets, and explanations of how they work under the hood so every reader (from novice to experienced) can follow and apply them.
1. Component Directives
Component directives are the most common and widely used type of directive in Angular.
A component is essentially a directive with template, styles, and logic combined, making it a reusable UI building block.
For example, <customer-details> can represent a customer card or a details section.
Need
Let's assume we want to create a dashboard with multiple details. We have two options:
Write all the details in a single HTML file and display it as a dashboard (a clustered approach, like a house without rooms, where a single hall is used for all purposes).
Create separate components for each detail and use the component directive feature to display them on a single dashboard.
So, Component Directives empower developers
To build modular, reusable, and maintainable UI units.
Without components, our application would be one large HTML file with scattered logic, making it difficult to scale.
Components help us divide the UI into small, manageable parts, each with its own responsibility.
Use Case
A dashboard with multiple widgets — each widget is a component.
A customer details page — you can break it down into:
<customer-table>(to list details)<update-customer>(form for updates)<customer-summary>(quick info card)
Each component is self-contained, so changes in one don’t affect others.
Example
customer-details.component.ts
import { Component } from '@angular/core'; @Component({ selector: 'customer-details', templateUrl: './customer-details.component.html', styleUrls: ['./customer-details.component.css'] }) export class CustomerDetailsComponent { customer = { id: 101, name: 'Raj Kumar', accountType: 'Savings', balance: 50000 }; }customer-details.component.html
<div class="customer-card"> <h2>{{ customer.name }}</h2> <p>Account Type: {{ customer.accountType }}</p> <p>Balance: ₹{{ customer.balance }}</p> </div>Usage in another component (e.g., app.component.html):
<h1>Banking Portal</h1> <customer-details></customer-details>Which Version?
Components were introduced in Angular 2 (2016).
Since Angular 2, components are the building blocks of every Angular application.
Takeaway:
Component directives are the heart of Angular applications. They turn complex UIs into smaller, reusable parts, each with its own template, logic, and styling.
2. Structural Directives
Using the Component directive, we can divide a large UI into small components and gather them together for the final output. Now, we will learn how to control sections within the same page of a component.
Structural directives are Angular directives that change the DOM structure by adding, removing, or repeating elements.
They are marked with a * prefix (like *ngIf, *ngFor) because they work with Angular’s template syntax.
Think of them as tools that reshape your HTML layout dynamically.
Need
Real-world UIs need sections that appear or disappear based on conditions.
You may also need to render lists of items dynamically from data (instead of hardcoding HTML).
Without structural directives, developers would have to write a lot of manual DOM manipulation code (using JS/TS), which is hard to maintain.
Use Case
Conditional Rendering → Show “Update Customer Form” only for managers.
- Use
*ngIfto include/exclude DOM sections.
- Use
Looping Through Data → Show a list of all customers dynamically.
- Use
*ngForto generate table rows or cards for each customer.
- Use
Switching Templates → Show different views (loading spinner, error message, or data view).
- Use
*ngSwitchfor multiple conditional layouts.
- Use
Examples
customer-list.component.html
<!-- Example 1: Conditional Rendering -->
<div *ngIf="isManager; else noAccess">
<h3>Update Customer Details</h3>
<form>
<!-- update form fields -->
</form>
</div>
<ng-template #noAccess>
<p>You don’t have permission to update customer details.</p>
</ng-template>
customer-list.component.html
<!-- Example 2: Looping Through Customers -->
<h2>Customer List</h2>
<ul>
<li *ngFor="let customer of customers">
{{ customer.name }} - {{ customer.accountType }} - ₹{{ customer.balance }}
</li>
</ul>
customer-list.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'customer-list',
templateUrl: './customer-list.component.html'
})
export class CustomerListComponent {
isManager = true;
customers = [
{ name: 'Raj Kumar', accountType: 'Savings', balance: 50000 },
{ name: 'Anita Sharma', accountType: 'Current', balance: 30000 },
{ name: 'Vikram Singh', accountType: 'Savings', balance: 70000 }
];
}
Which Version?
Structural directives were present from the beginning of Angular 2 (2016).
In AngularJS (1.x):
- Similar concepts existed (
ng-if,ng-repeat), but Angular 2+ made them more powerful and consistent.
- Similar concepts existed (
Takeaway:
Structural directives are like architects of the DOM.
They decide what exists in the DOM and what doesn’t, based on conditions or data.
So now, with two directives, we have the power to convert big UI tasks into small components, and within a component, we have control over sections or parts as well.
3. Attribute Directives
Attribute directives are used to change the appearance or behavior of existing DOM elements without altering their structure.
They are applied as attributes on elements (e.g., [ngClass], [ngStyle]).
Think of them as stylists and behavior enhancers of the DOM.
Need
Sometimes we don’t want to remove or add DOM elements — instead, we just want to change how an existing element looks or behaves.
Example needs:
Apply dynamic CSS classes/styles.
Enable/disable elements based on conditions.
Add role-based access restrictions without duplicating HTML.
Without attribute directives, you would write long, messy conditional logic in the template or component, making code less readable and reusable.
Use Case
Dynamic Styling → Highlight a customer with low balance in red. (
[ngClass]/[ngStyle])State Change → Disable the update button if user is not a manager.
Custom Behavior → Build a custom directive that validates input fields (e.g., allow only numbers) or hides content based on roles.
Examples
Example 1: Built-in Attribute Directives
<!-- customer-list.component.html -->
<ul>
<li *ngFor="let customer of customers"
[ngClass]="{'low-balance': customer.balance < 40000}">
{{ customer.name }} - ₹{{ customer.balance }}
</li>
</ul>
customer-list.component.css
.low-balance {
color: red;
font-weight: bold;
}
Example 2: Custom Attribute Directive
A directive to highlight an element when hovered:
highlight.directive.ts
import { Directive, ElementRef, HostListener, Renderer2 } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(private el: ElementRef, private renderer: Renderer2) {}
@HostListener('mouseenter') onMouseEnter() {
this.renderer.setStyle(this.el.nativeElement, 'backgroundColor', 'yellow');
}
@HostListener('mouseleave') onMouseLeave() {
this.renderer.removeStyle(this.el.nativeElement, 'backgroundColor');
}
}
Usage in HTML
<p appHighlight>Hover over this text to see highlight effect</p>
Which Version?
Attribute directives were available from Angular 2 onwards.
In AngularJS (1.x), similar functionality existed with
ng-class,ng-style, and custom directives.Angular 2+ streamlined this into clear attribute directives, which work more consistently with Angular’s change detection and rendering.
Takeaway:
Attribute directives are the makeup artists of Angular.
They don’t change the DOM structure, but they enhance how elements look and behave dynamically.
Okay, so we're finished now.
Are we?
we haven't learned much about custom directives yet.
Without creating our own directive, we might not feel like skilled developers. So, let's dive into learning about custom directives now.
Are you excited to create your own directive? Let's get started!
4. Custom Directives
Custom directives are user-defined directives that extend Angular’s power beyond built-in ones (*ngIf, ngClass, etc.).
They let developers create reusable logic for controlling the DOM dynamically based on custom conditions or inputs.
Think of them as your own rules for how the DOM should behave.
Need
Built-in directives solve common problems (loops, conditions, styling).
But in real-world apps, you often need project-specific logic:
Show/hide content based on user role/permission.
Disable/enable elements dynamically.
Apply domain-specific behaviors (e.g., masking input, validating special formats).
Without custom directives, you’d have to repeat conditional logic in multiple templates → messy and hard to maintain.
Use Case
Role-based access control: Show the update form only if the user is a manager.
Validation logic: Automatically restrict an input to numeric values.
UI behavior: Highlight, toggle, animate, or dynamically style elements based on data.
In our banking app example: Back-office users should NOT see the “Update Customer” form. Only managers should.
Example
Step 1: Create the directive
Use a command like ng g directive <directive_name>
// role-based.directive.ts
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[appShowIfRole]'
})
export class ShowIfRoleDirective {
private userRole: string = 'backoffice'; // example current user role
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef
) {}
@Input() set appShowIfRole(role: string) {
this.viewContainer.clear();
if (this.userRole === role) {
// Render the element if roles match
this.viewContainer.createEmbeddedView(this.templateRef);
}
}
}
Step 2: Use in HTML
<!-- customer.component.html -->
<h2>Customer Details</h2>
<!-- Visible only for managers -->
<div *appShowIfRole="'manager'">
<h3>Update Customer Details</h3>
<form>
<!-- form fields -->
</form>
</div>
<!-- Backoffice users won't see the form at all -->
Step 3: Expected Behavior
If
userRole = 'manager'→ Update form is visible.If
userRole = 'backoffice'→ Form is not rendered in DOM.
In this example, I have hardcoded the role, but you can practice by building a backend API that will fetch the user role after login and use that in your directive.
Which Version?
AngularJS (1.x): Custom directives existed (using
directive()API).Angular 2+: Creating custom directives became much easier and more powerful with
@Directivedecorator.They integrate seamlessly with Angular’s change detection and template syntax.
Takeaway:
Custom directives are your way of saying:
“Hey Angular, I need a new rule for my DOM, because my project has unique needs.”
They let you encapsulate logic once and reuse it across your app → cleaner, DRY, and maintainable code.
Now we have reached a pro level and can confidently say we are an Angular developer with strong control over the DOM using directives.
If still not satisfied and curiosity is still at its peak, let's get into the internals of Angular directives and reach the expert level.
we’ll take one example for each type of directive and explain the internal mechanism (with code + how Angular processes it).
Internals of Angular Directives
1. Component Directive (Example: CustomerDetailsComponent)
What we write:
@Component({
selector: 'customer-details',
template: `<p>{{ customer.name }}</p>`
})
export class CustomerDetailsComponent {
customer = { name: 'Raj Kumar' };
}
How Angular processes it internally:
Angular sees
<customer-details>in the DOM.It looks up the selector in the component’s
@Componentmetadata.Angular replaces that element with the component’s template.
The
CustomerDetailsComponentclass instance is created and bound to the template.Change detection updates the DOM whenever
customerchanges.
Internally, Angular treats components as directives with templates (a specialized directive).
2. Structural Directive (Example: *ngIf)
What we write:
<div *ngIf="isManager">Update Customer Details</div>
What Angular actually does under the hood:
- Angular desugars (translates) this into a
<ng-template>:
<ng-template [ngIf]="isManager">
<div>Update Customer Details</div>
</ng-template>
How Angular processes it:
NgIfdirective receives the input (isManager).Internally, it uses
ViewContainerRefandTemplateRef.If condition is
true→ Angular inserts the template into the DOM.If condition is
false→ Angular removes it.
Pseudo implementation:
@Directive({ selector: '[ngIf]' })
export class NgIf {
constructor(private view: ViewContainerRef, private template: TemplateRef<any>) {}
@Input() set ngIf(condition: boolean) {
this.view.clear();
if (condition) {
this.view.createEmbeddedView(this.template);
}
}
}
This is why the element isn’t just hidden — it’s actually removed from DOM memory when false.
3. Attribute Directive (Example: ngClass)
What we write:
<p [ngClass]="{'highlight': isImportant}">Customer Details</p>
How Angular processes it:
Angular parses
[ngClass]binding and passes the object{ 'highlight': true/false }toNgClassdirective.NgClassinternally uses Angular’sRenderer2service to add or remove CSS classes dynamically.
Pseudo implementation:
@Directive({ selector: '[ngClass]' })
export class NgClass {
constructor(private el: ElementRef, private renderer: Renderer2) {}
@Input() set ngClass(classes: any) {
for (let c in classes) {
if (classes[c]) {
this.renderer.addClass(this.el.nativeElement, c);
} else {
this.renderer.removeClass(this.el.nativeElement, c);
}
}
}
}
Unlike *ngIf, it doesn’t remove the element — it just changes its appearance/behavior.
Expert-Level Takeaway
Component directives → Create new UI blocks, backed by a class + template.
Structural directives → Use
TemplateRef+ViewContainerRefto add/remove DOM structure dynamically.Attribute directives → Use
ElementRef+Renderer2to change styles/behavior of existing elements.
In short:
Component = New DOM block
Structural = DOM architect
Attribute = DOM stylist/behavior enhancer
1) Alternatives to Angular Directives
Directives are essentially “DOM behavior controllers.”
In other ecosystems/frameworks, you’ll find similar but slightly different mechanisms:
a) React (Hooks & JSX Conditions)
React doesn’t have directives.
Instead, you write conditional rendering and behaviors directly in JSX:
{isLoggedIn && <p>Welcome User</p>}For DOM manipulation, you use hooks (useEffect, refs) or libraries.
Alternative to custom attribute directives = custom hooks or higher-order components.
b) Vue.js (Directives but Simpler)
Vue has directives like
v-if,v-for,v-show(very similar to Angular’s*ngIf,*ngFor).Custom directives in Vue exist, but are less powerful (mostly used for DOM manipulation like focus, scroll).
For logic-heavy conditions, Vue prefers components.
c) Svelte (Compile-Time Directives)
Svelte has
#if,#each,#awaitblocks.They look like Angular structural directives but are compiled away → no runtime cost.
DOM manipulation is just JavaScript + bindings, no directive system needed.
d) Web Components (Native HTML APIs)
Instead of framework directives, you can use custom elements + attributes with native browser APIs (
customElements.define).Example:
<my-show-if condition="true">Hello</my-show-if>Works without Angular, but less feature-rich.
e) Direct DOM Libraries
Tools like Alpine.js or Lit use lightweight attribute-based syntax.
Example (Alpine.js):
<div x-show="isOpen">Content</div>
This feels like Angular attribute directives, but minimal and framework-agnostic.
2) Future of Angular Directives
Angular is moving towards simplicity, performance, and better DX (Developer Experience).
a) Standalone APIs
Angular (v14+) introduced standalone directives/components (no NgModules needed).
Future = directives/components easier to create and use without boilerplate.
b) Signals (Angular v16+)
Signals provide reactivity without heavy change detection.
Structural directives like
*ngIfand*ngFormay internally shift to signals for performance.Example: Instead of
@Input() condition, future custom directives might directly react to signals.
c) Reduced Need for Some Directives
With better template syntax (microsyntax) and RxJS/Signals integration, developers may need fewer custom directives.
Many use cases might shift to:
Reusable components
Reactive state control
Direct template bindings
d) Framework Trend
React → JSX conditions (no directives).
Vue & Angular → still keep directives (for ergonomics).
Svelte → compiles them away.
Summary
Alternatives: React (hooks), Vue (directives), Svelte (compile-time blocks), Alpine.js (lightweight attributes), Web Components.
Future in Angular:
Directives will stay but may become lighter & signal-driven.
Standalone directives make them easier to use anywhere.
Thank you so much for reading!
I really appreciate your time and curiosity. My goal with this blog is to make complex topics easy and enjoyable to learn. If you found this helpful, I’d love for you to stay connected—your support and feedback motivate me to write more.