Angular Directives: Now Enhance Your Angular App UI Easily

Angular Directives: Now Enhance Your Angular App UI Easily

23 Sep 2024
Intermediate
10.4K Views
40 min read
Learn with an interactive course and practical hands-on labs

Self-Paced Angular Certification Course

Angular Directives

Angular Directives are one of Angular's key building components, allowing you to create dynamic, reusable components. Just Imagine you're developing an Angular app and need additional control over how your HTML behaves or interacts with the user. This is where Angular Directives come into play! In Angular, directives make your forms dynamic. They are essentially the secret sauce that allows you to extend HTML beyond its default capabilities, and believe me, once you start utilizing them, you'll understand how much they can simplify your code.

In this Angular Tutorial, I am gonna show you how Angular Directives works on UI along with HTML, We will learn What are Directives in Angular, the Types of Directives in Angular, and many more.

What are Directives in Angular?

Angular directives are essential elements of Angular apps. They are special markup tokens that instruct the Angular framework to act on a DOM element. Directives can be used to do a range of things, including altering the DOM, adding behavior to elements, and controlling the layout of a web application. They allow developers to reuse angular components and expand HTML syntax to construct dynamic and interactive online apps.

Directives in Angular

Types of Directives in Angular

There are 4 Types of Directives in Angular:

  1. Component Directives
  2. Attribute Directives
  3. Structural Directives
  4. Custom Directives

Types of Directives in Angular

You can see that here we explained the different types of directives in Angular with examples.

1. Components Directives

The directive with a template specification and this type of directive is the most common directive type in Angular. Typically, a Component is a directive with a template. @Component decorator extends the @Directive decorator with template-oriented features. A component class is declared using the @Component decorator. @Component decorator contains metadata about the component i.e. selector, templateURL, styleUrls, etc.

Example of Component Directive

import {Component} from '@angular/core' 
 
@Component({
  selector: 'app-hello',
  template: `<h1>Hello, World!</h1>})
 
export class AppComponent{}

Explanation

Here, "AppComponent" is a component directive that displays "Hello, World!" on the UI. Component directives have their own lifecycle hooks and are fundamental to Angular’s architecture. This code imports the Component class from the Angular core library and creates an Angular component called AppComponent. The @Component decorator specifies details about the component, such as its HTML template and styles.

2. Attribute Directive

The directive that changes the appearance or behavior of an element, component, or other directives. Attribute directives are used to change the appearance or behavior of an existing DOM element. ngStyle and ngClass are the commonly used examples for attribute directives. Exploring attribute directives is an essential part of Angular JS training.

Common directivesDetails
NgStyleIt adds and removes a set of CSS classes.
NgClassIt adds and removes a set of HTML styles.
NgModelIt adds two-way data binding to an HTML form element.

NgStyle

This is used to configure multiple inline styles for HTML elements.

1. Setting inline styles with NgStyle

 import { Component } from '@angular/core'; 
 
 @Component({ 
 selector: 'Satya-App', 
 template: `<button style='color:green' [ngStyle]="MyStyle()">Satyaprakash Samantaray</button>`
 }) 
 export class AppComponent { 
 isBold: boolean = true; 
 fontSize: number = 30; 
 isItalic: boolean = true; 
 
 MyStyle() { 
 let mystyles = { 
 'font-weight': this.isBold ? 'bold' : 'normal', 
 'font-style': this.isItalic ? 'italic' : 'normal', 
 'font-size.px': this.fontSize 
 }; 
 
 return mystyles; 
 } 
 } 

Explanation

Here I added a button control in the template part with a style sheet named MyStyle(). This MyStyle CSS method is defined as below.

 MyStyle() { 
 let mystyles = { 
 'font-weight': this.isBold ? 'bold' : 'normal', 
 'font-style': this.isItalic ? 'italic' : 'normal', 
 'font-size.px': this.fontSize 
 }; 

 return mystyles;

Output

Output of Ngstyle attribute directive

2. Usage of NgStyle in your component

  • Use NgStyle to set numerous inline styles at the same time, depending on the component's state.
  • To utilize NgStyle, define a method in the component class.
  • In the following example, setCurrentStyles() replaces the property currentStyles with an object defining three styles based on the state of three other component values.
  • currentStyles: Record = {};
    /* . . . */
    setCurrentStyles() {
      // CSS styles: set per current state of component properties
      this.currentStyles = {
        'font-style': this.canSave ? 'italic' : 'normal',
        'font-weight': !this.isUnchanged ? 'bold' : 'normal',
        'font-size': this.isSpecial ? '24px' : '12px',
      };
    }
    

    Explanation

    Here, To set the element's styles, add a ngStyle property binding to "currentStyles" like the following way
    <div [ngStyle]="currentStyles">
      This div is initially italic, normal weight, and extra large (24px).
    </div>
    
    For this use scenario, Angular applies the styles both at initialization and when there are changes. To accomplish this, the whole example calls setCurrentStyles() first with ngOnInit() and then when the dependant properties change due to a button click. However, these steps are not required to use ngStyle on their own. This optional implementation can be seen in the live example or downloaded as app.component.ts and app.component.html.

    NgClass

    This is used to set the class attribute of the html element to apply the style.

    Example for NgClass

     import { Component } from '@angular/core'; 
     
     @Component({ 
     selector: 'Satya-App', 
     template: `<button class='colorClass' [ngClass]='applyClasses()'>Satyaprakash Samantaray</button>`, 
     styles: [`.boldClass{ 
     font-weight:bold; 
     font-size : 30px; 
     } 
     
     .italicsClass{ 
     font-style:italic; 
     } 
     
     .colorClass{ 
     color:Red; 
     }`] 
     }) 
     export class AppComponent { 
     applyBoldClass: boolean = true; 
     applyItalicsClass: boolean = true; 
     
     applyClasses() { 
     let classes = { 
     boldClass: this.applyBoldClass, 
     italicsClass: this.applyItalicsClass 
     }; 
     
     return classes; 
     } 
     } 

    Explanation

    In this NgClass we are using the class attribute of the HTML element to apply styles.

     template: `<button class='colorClass' [ngClass]='applyClasses()'>Satyaprakash Samantaray</button>`,
    

    Output

    Output of NgClass Attribute Directive

    3. Structural Directive

    The directive changes the DOM layout by adding or removing the DOM elements. Structural directives are used to alter the layout by adding, removing, and replacing elements in the DOM. Asterisk (*) is used when these directives are used with the HTML elements. *ngIf, *ngFor, *ngSwitch are some commonly used structural directives in angular.

    structural directivesfunctionality
    NgIfIt conditionally creates or disposes of subviews from the template.
    NgForIt repeats a node for each item in a list.
    NgSwitchIt is a set of directives that switch among alternative views.

    1. NgIf

    It is used to create or remove a part of the DOM tree depending on a condition.

    Example for ngIf

     import { Component } from '@angular/core'; 
     
     @Component({ 
     selector: 'Satya-App', 
     template: `<div style='color:blue' *ngIf="true">You can See Satyaprakash....</div>`
     }) 
     export class AppComponent { 
     
     } 

    Here If ngif= true So, the text will be visible on the web page.

      template: `<div style='color:blue' *ngIf="true">You can See Satyaprakash....</div>`
    

    Output

    Output of NgIf Structural Directive

    2. NgFor

    It is used for iteration like showing a list of items using loops.

    Example for ngFor: TS Code

    import { Component } from '@angular/core'; 
     
     @Component({ 
     selector: 'Satya-App', 
     templateUrl: './app.component.html', 
     }) 
     export class AppComponent { 
     employees: any[] = [ 
     { 
     code: '1001', name: 'Satya', gender: 'Male', 
     annualSalary: 5500, dateOfBirth: '25/6/1988' 
     }, 
     { 
     code: '1002', name: 'Mohit', gender: 'Male', 
     annualSalary: 5700.95, dateOfBirth: '9/6/1982' 
     }, 
     { 
     code: '1003', name: 'Rohit', gender: 'Male', 
     annualSalary: 5900, dateOfBirth: '12/8/1979' 
     }, 
     { 
     code: '1004', name: 'Satyaprakash Samantaray', gender: 'Female', 
     annualSalary: 6500.826, dateOfBirth: '14/10/1980' 
     }, 
     ]; 
     } 

    Explanation

    I have created a class named employees and inserted values into its corresponding properties.

     employees: any[] = [ 
     { 
     code: '1001', name: 'Satya', gender: 'Male', 
     annualSalary: 5500, dateOfBirth: '25/6/1988' 
     },
    

    Example for ngFor: HTML Code

     <!DOCTYPE html> 
     <html> 
     <head> 
     <title></title> 
     <meta charset="utf-8" /> 
     <style> 
     table { 
     font-family: arial, sans-serif; 
     border-collapse: collapse; 
     width: 100%; 
     } 
     
     td, th { 
     border: 1px solid #dddddd; 
     text-align: left; 
     padding: 8px; 
     } 
     
     tr:nth-child(even) { 
     background-color: #dddddd; 
     } 
     </style> 
     </head> 
     <body> 
     <table align="center" border="1" cellpadding="4" cellspacing="4"> 
     <thead> 
     <tr> 
     <th style="background-color: Yellow;color: blue">Code</th> 
     <th style="background-color: Yellow;color: blue">Name</th> 
     <th style="background-color: Yellow;color: blue">Gender</th> 
     <th style="background-color: Yellow;color: blue">Annual Salary</th> 
     <th style="background-color: Yellow;color: blue">Date of Birth</th> 
     </tr> 
     </thead> 
     <tbody> 
     <tr *ngFor='let employee of employees'> 
     <td>{{employee.code}}</td> 
     <td>{{employee.name}}</td> 
     <td>{{employee.gender}}</td> 
     <td>{{employee.annualSalary}}</td> 
     <td>{{employee.dateOfBirth}}</td> 
     </tr> 
     <tr *ngIf="!employees || employees.length==0"> 
     <td colspan="5"> 
     No employees to show in the page.... 
     </td> 
     </tr> 
     </tbody> 
     </table> 
     </body> 
     </html> 
    

    Here NgFor is used to display a list of items using repetitive loops that are data of the employee's class.

     <tr *ngFor='let employee of employees'> 
     <td>{{employee.code}}</td> 
     <td>{{employee.name}}</td> 
     <td>{{employee.gender}}</td> 
     <td>{{employee.annualSalary}}</td> 
     <td>{{employee.dateOfBirth}}</td> 
     </tr> 
    

    Output

    Output of NgFor Structural Directive

    3. NgSwitch

    It can be used as a switch case in OOPS. It is used to select one case among various cases. Angular will add only the selected option HTML markup into the DOM.

    app.component.ts with NgSwitch implementation

     import { Component } from '@angular/core'; 
     
     @Component({ 
     selector: 'Satya-App', 
     template: `<h2>{{title}}</h2> 
     <p *ngIf="showElement">Show Element</p> 
     <div [ngSwitch]="inpvalue"> 
     <p style='color:blue' *ngSwitchCase="1">You have selected M S Dhoni</p> 
     <p style='color:blue' *ngSwitchCase="2">You have selected Sachin Tendulkar</p> 
     <p style='color:blue' *ngSwitchCase="3">You have selected Satyaprakash Samantaray</p> 
     <p style='color:red' *ngSwitchDefault>Sorry! Invalid selection....</p> 
     </div>` 
     }) 
     export class AppComponent { 
    
     inpvalue: number = 3; 
     } 
    

    You can display one element from among several possible elements, based on a switch condition. Angular puts only the selected element into the DOM. Here we are using ngswitchcase to apply switch case and ngswitch default is for invalid selection. Using the switch directive we can show output by passing the value of the pvalue property in the AppComponent class.

    Output

    For valid selection >>

    Output of NgSwitch valid selection

    For Invalid selection >>

    Output of NgSwitch invalid selection

    You can check the code compilation status in the command prompt during a change in code using Visual Studio.

    Code Compilation Status

    4. Custom Attribute Directive

    Custom directives can also be created if any of the above directives do not solve our purpose for the requirement. Custom attribute directives can be created by using @Directive decorator. Custom attribute directives can be used to modify the background color, and text information of an HTML element, and that process is called a host element. To change the UI look angular provides an ElementRef class that can directly access DOM.

    Creating a Custom Directive

    Let's create a folder under an app called directives. Under directives create a file called red.directive.ts as given below:

     import { Directive, ElementRef } from '@angular/core';
     
     @Directive({ 
     selector: '[ColorRed]' 
     })
     export class MyCustomDirective {
     constructor(elRef: ElementRef) {
     elRef.nativeElement.style.color = 'darkred';
     }
     } 
    

    Make a directive named as myRed directive. We can use it with HTML elements such as <p> and <div>, the text color within that element will be red. The @Directive is used as an angular directive to retrieve directive configuration metadata. To use our custom directive in our angular project follow the below code to set up in the application module.

     import { BrowserModule } from '@angular/platform-browser';
     import { NgModule } from '@angular/core';
     
     import { AppComponent } from './app.component';
     import { MyRedDirective } from './directives/red.directive';
     
     @NgModule({
     declarations: [
     AppComponent,
     MyCustomDirective
     ],
     imports: [
     BrowserModule
     ],
     providers: [],
     bootstrap: [AppComponent]
     })
     export class AppModule { }
    
    app.component.ts
     import { Component } from '@angular/core';
     
     @Component({
     selector: 'Satya-App',
     templateUrl: './app.component.html'
     })
     export class AppComponent { 
     txtsize = '25px';
     colors = ['red', 'blue', 'orange'];
     myColor = '';
     }
    
    app.component.html
    <!DOCTYPE html> 
     <html> 
     <head> 
     <title></title> 
     <meta charset="utf-8" /> 
     <style> 
     table { 
     font-family: arial, sans-serif; 
     border-collapse: collapse; 
     width: 100%; 
     } 
     
     td, th { 
     border: 1px solid #dddddd; 
     text-align: left; 
     padding: 8px; 
     } 
     
     tr:nth-child(even) { 
     background-color: #dddddd; 
     } 
     </style> 
     </head> 
     <body> 
     <p ColorRed>Custom Attribute Directive By Satyaprakash</p> 
     </body> 
     </html> 
    

    we are ready to use our directive in the HTML template. Find the code snippet.

    <body> 
     <p ColorRed>Custom Attribute Directive By Satyaprakash</p> 
     </body>
    
    app.module.ts
     
     import { BrowserModule } from '@angular/platform-browser';
     import { NgModule } from '@angular/core';
     
     import { AppComponent } from './app.component';
     import { MyRedDirective } from './directives/red.directive';
     
     @NgModule({
     declarations: [
     AppComponent,
     MyCustomDirective
     ],
     imports: [
     BrowserModule
     ],
     providers: [],
     bootstrap: [AppComponent]
     })
     export class AppModule { }

    Here I import a custom attribute directive reference to configure the custom attribute that I have created.

      import { MyRedDirective } from './directives/red.directive';
     
     @NgModule({
     declarations: [
     AppComponent,
     MyCustomDirective
     ],
    

    Output

    Output of Creating a Custom Directive

    Difference between structural directive and attribute directive

    Structural directives are used to add, remove, and replace elements in DOM. On the other hand, attribute directives are used to change the appearance or behavior of an existing element.

    Passing Input to Directives

    Angular's @Input decorator allows directives to receive data from their parent components. This is how it works.

    • Define a @Input property: In your directive's TypeScript code, use the @Input() decorator to indicate which property will receive data. This informs Angular that the property can be bound directly from the template.
    • Pass data via property binding: In your component's HTML template, use the property binding syntax ([directiveName]="data") to bind a value from your component to the directive's @Input property.

    Read More:

    Other Directives

    1. Host Listener Directive

    A host listener directive responds to events like as mouse clicks and keyboard presses. Let's write a directive that changes the color of the text when the mouse hovers over it.

    Example: HoverTextColorDirective

    // hover-text-color.directive.ts
    import { Directive, ElementRef, HostListener, Renderer2 } from '@angular/core';
    
    @Directive({
      selector: '[appHoverTextColor]'
    })
    export class HoverTextColorDirective {
      constructor(private el: ElementRef, private renderer: Renderer2) {}
    
      @HostListener('mouseenter') onMouseEnter() {
        this.changeTextColor('blue');
      }
    
      @HostListener('mouseleave') onMouseLeave() {
        this.changeTextColor(null);
      }
    
      private changeTextColor(color: string | null) {
        this.renderer.setStyle(this.el.nativeElement, 'color', color);
      }
    }
    

    Usage in a template

    <pappHoverTextColor>Hover over this text to change its color.</p>
    

    Output

    Hovering over the paragraph turns the text color to blue.
    When the mouse is released, the color returns to its default setting.
    

    2. Input-Bound Directive

    An input-bound directive allows you to include dynamic data in the directive. Let's write an input-bound directive that changes the font size of an element dynamically.

    Example: DynamicFontSizeDirective

    // dynamic-font-size.directive.ts
    import { Directive, ElementRef, Renderer2, Input, OnChanges } from '@angular/core';
    
    @Directive({
      selector: '[appDynamicFontSize]'
    })
    export class DynamicFontSizeDirective implements OnChanges {
      @Input() appDynamicFontSize: string = '16px';  // default font size
    
      constructor(private el: ElementRef, private renderer: Renderer2) {}
    
      ngOnChanges() {
        this.renderer.setStyle(this.el.nativeElement, 'font-size', this.appDynamicFontSize);
      }
    }
    

    Usage in the template:

    <p [appDynamicFontSize]="'24px'">This text has a font size of 24px.</p>
    <p [appDynamicFontSize]="'18px'">This text has a font size of 18px.</p>
    

    Output

    The first paragraph’s text appears in 24px font size.
    The second paragraph’s text appears in 18px font size.
    

    Creating a Custom Directive in Angular

    Angular also lets you make custom attribute or structure directives. Let's have a look at how to create a basic custom directive that changes the background color of an element on hover.
    import { Directive, ElementRef, HostListener, Renderer2 } from '@angular/core';
    @Directive({
      selector: '[appHoverHighlight]'
    })
    export class HoverHighlightDirective {
      constructor(private el: ElementRef, private renderer: Renderer2) {}
    
      @HostListener('mouseenter') onMouseEnter() {
        this.renderer.setStyle(this.el.nativeElement, 'background-color', 'yellow');
      }
    
      @HostListener('mouseleave') onMouseLeave() {
        this.renderer.removeStyle(this.el.nativeElement, 'background-color');
      }
    }
    

    Explanation

    In this example:
  • We designed a directive named HoverHighlightDirective.
  • We utilize @HostListener to listen for "mouseenter" and "mouseleave" events.
  • We utilize Renderer2 to safely interact with the DOM and change the background color.
  • Usage in a template

    <p appHoverHighlight>Hover over this text to see the effect!</p>
    

    When to Use Directives in Angular

    Directives are especially useful when it comes to:
  • Reuse behavior across several elements: Rather than repeating the same logic, you may develop a reusable directive
  • Encapsulate the logic: Keep logic separate from components by implementing directives for tasks such as validation, style, and event handling.
  • Simplify your templates: Directives make your templates tidy and maintainable by abstracting logic into reusable components.
  • Benefits of Using Directives

  • Modular Code: Directives make it easy to encapsulate and reuse logic between components.
  • Clean Templates: By delegating behavior to directives, Angular templates become more concise and readable.
  • Maintainability: Directives improve your application's maintainability because they are reusable and self-contained.
  • Customizable Behaviors: You can simply expand HTML components with custom behaviors tailored to your application's requirements.
  • Summary

    Once we say that the components are the/ building blocks of the Angular applications, but eventually, we are saying that the directives are the building blocks of Angular applications that are used to deal with DOM elements. In this article, you learned about the various types of directives in Angular with its examples. I hope you will find it useful when you will work with your Angular Application. And wait..! if you also want to become a pro in Angular then please consider our Angular Certification Online Training plus you will get a lot of Benefits of obtaining Angular certification.

    Read More: Is Angular Certification Worth It in 2024? Top 10 Certifications Compared

    FAQs

    Angular directives are an excellent method to encapsulate reusable behaviors; directives can add attributes, CSS classes, and event listeners to an element. The directive composition API allows you to apply directives to a component's host element from within its TypeScript class.

    In simple terms, a decorator is a TypeScript feature, not an Angular thing. However, decorators are widely utilized in Angular. A directive, on the other hand, is an Angular feature or concept rather than a TypeScript item.

    Angular will not let you. You can only apply one structural directive to an element. The explanation is simple. Structural directives can perform complicated operations on the host element and its descendants.

    The ngIf directive removes or recreates a piece of the DOM tree based on an expression. If the expression supplied to ngIf returns a false value, the element is removed from the DOM; otherwise, a clone of the element is put into the DOM.

    Take our Angular skill challenge to evaluate yourself!

    In less than 5 minutes, with our skill challenge, you can identify your knowledge gaps and strengths in a given skill.

    GET FREE CHALLENGE

    Share Article
    About Author
    Satyaprakash Samantaray (An Author and Blogger)

    He is passionate about Microsoft .NET technology and likes to share knowledge with the .NET developer's community. He is a contributor in Microsoft and the ASP.NET developer community.
    Accept cookies & close this