Categories
Angular Java Script Tutorials

Understand Angular Directive with Example [Video]

Angular directive makes more sense when used in an example. The interesting example will make things fun to understand and follow. In our scenario we will handle the images that are failed to load.

If you are more of a video person that I have also attached the video the end of the article

Watch Video

Introduction

Angular directive add super power to HTML. In other terms it extends the functionality of HTML elements.

There are two types of angular directives.

  1. Attribute Directive
  2. Structual Directive

Attribute Directive basically modifies the appearance and behavior of DOM element. Styling a background color of paragraph tag is one of the example. Structural Directive do things like wrapping elements and manipulation for structural change or Layout. For the sake of this article, we will use the former type.

Creating Custom Angular Attribute Directive

First of all let’s create a blank angular app

ng new sample-app
// after going through the interactive CLI which might asks for 
// whether we need angular routing and CSS pre-processor to choose

After serving the app we are welcome with this screen

Sample app when we generate angular new blank app used in explaining Angular directive with example
Welcome screen is changed quite a bit. At the time of writing I am using angular 8.2.14 which rarely matters what we want to achieve in this article.

Use case

What happen when an HTML img fails to load. Browser displays the alt or alternate text instead. What if we have away to load a placeholder/fallback image. That where our directive will comes into play and that what we are making next.

Let’s go to the terminal and generate new directive.

ng g directive imgFallback

This command will generate a directive, add it to the declarations block entry module i-e app.module.ts (if no module is specified in the command)

Now let’s modify our newly generated directive

import { Directive, ElementRef } from '@angular/core';

@Directive({
  selector: '[appImgFallback]'
})
export class ImgFallbackDirective {

  constructor(el: ElementRef) {
    console.log(el.nativeElement);
  }

}

The constructor receives the reference of current element where directive is used. We will log the current element to console. Lets use this Angular Directive by modifying app.component.html

<div>
  <img src="http://placekitten.com/g/200/300"  appImgFallback alt="Placekitten Placeholder">
</div>

Previously I have use lorempixel for placeholder but that does not work for some reason. I have borrowed a cat from placekitten.

Picture of Cat from placekitten website as a placeholder to describe angular directive from technbuzz.com
The browser logs the img element which confirms that our directive works

Let’s fail our img by modifying the src to url that does not exist.

<div>
  <img src="http://urldoesnotexist.com/g/200/300"  appImgFallback alt="Placekitten Placeholder">
</div>
Image fails to load but alt tag is diplayed instead, building the stage for angular directive image fallback technbuzz.com
Thanks to alt tag that shows up for failed images. It is a must for accessibility and SEO as well

Solution

Let’s use our Angular directive to handle the above scenario. We can use error event of html img element when it fails to load.

In angular we can directly use (error) event on image tag or better — we can our directive to listen to such events. Let’s upgrade our directive.

//..............
constructor(private el: ElementRef) {
    console.log(el.nativeElement);
  }

  @HostListener('error') onError () {
    this.el.nativeElement.src = '../assets/placeholder.png'
  }
//.............

The only that change here is the use of Host Listener. We are using host Listener to listen for error event and update the src attribute accordingly. I am linking to image in the assets folder. You can use the image of your choice and the result becomes

For the first attempt image fails to load (that can be seen on developer tools). Then our directive kicks and replaces the failed url with local replacement. Hence we see the placeholder image.

Now we can use this directive where ever we want in the entirety of our Angular App. There is one caveat though; If for some reason the image in asset folder failed to load than we are in the infinite loop. Because the onError function executes on every fail attempt. Which can simply be fixed with a flag variable. Our html remains the same but the final code listing fore the directive becomes.

    import { Directive, ElementRef, HostListener } from '@angular/core';

@Directive({
  selector: '[appImgFallback]'
})
export class ImgFallbackDirective {
  alreadyTried: boolean = false;

  constructor(private el: ElementRef) { }
  
  @HostListener('error') onError(){
    if (!this.alreadyTried) {
      this.el.nativeElement.src = './../assets/placeholder.png'
    }

    this.alreadyTried = true
  }
}

Screencast

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.