Introduction to Angular Directives

Angular directives plays a major role in an angular application. So we say, Components are the building blocks of an Angular application, but you know Component is actually a directive. Basically a directive is a function that executes whenever the angular compiler finds it in the DOM.

All the directives have their own respective names like ng-repeat or some custom names. So angular divides these directives into three types such as,

  • Components
  • Attribute directive
  • Structural directive

Components

As we saw in previous blogs, angular is streamlined on component-based architecture.

All the components are defined with @Component decorator. Basically these components are just directives with their own templates.

But behind the scenes they use directive API’s and it’s very easy to define an component in Angular.

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular';
}

It is a directive which has templates. The other two directives doesn’t have a template instead they are strongly dependent on DOM manipulation.

Attribute directive

Attribute directives are used to apply conditional styles to HTML elements or changing the behavior of the component dynamically based upon a property etc. Basically it just manipulates the DOM based upon a condition.

So let us a see a small example of how we can create this attribute directive. In this example we are going to create an highlighter directive which highlights a text when you mouse hover on it.

highlight.directive.ts

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

@Directive({
  selector: '[appHighlight]'
  //we have to use this selector to access this directive
})
export class HighlightDirective {
  constructor(private el: ElementRef) { }
  @Input('appHighlight') highlightColor: string;

  @HostListener('mouseenter') onMouseEnter() {
    this.highlight(this.highlightColor);
  }

  @HostListener('mouseleave') onMouseLeave() {
    this.highlight(null);
  }

  private highlight(color: string) {
    this.el.nativeElement.style.backgroundColor = color;
  }
}

A directive needs to be accessed by it’s selector. Here we have given [appHighlight] as the directive selector name. Basically it receives an input color from the DOM and it changes the attribute of the DOM depends upon the color given to this directive.

In attribute directives, we use ElementRef to manipulate it’s behavior in the DOM.

app.module.ts

import { HighlightDirective } from './highlight.directive';

@NgModule({
  declarations: [
    HighlightDirective
  ]
})
export class AppModule { }

If you want to use this directive you need to import this directive in your respective module.

app.component.html

<p [appHighlight]="'red'">Hover on me! Highlight me!</p>

<p [appHighlight]="'green'">
  Hover on me! Highlight me too!
</p>

In the above html, we are using this directive in our html as [appHighlight] which will be received by the respective directive using @Input() decorator. So if you hover on it, the respective color will be displayed.

Attribute directive demo => https://bit.ly/387jJpH

Structural directive

Structural directives are used to create and destroy DOM elements. There are many predefined structural directives such as ngIf, hidden, ngClass etc. Basically these directives will change the entire HTML structure and we need to be very careful whenever we are using these structural directives.

Let us see an example of how we can create and use structural directives. In this example, we are going create our own custom IF directive.

myCustomIf.directive.ts

import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';

@Directive({
    selector: '[myCustomIf]'
    //we will use this selector name to access the directive
})

export class MyCustomIfDirective {
    constructor(
        private templateRef: TemplateRef<any>,
        private viewContainer: ViewContainerRef) { }

    @Input() set myCustomIf(condition: boolean) {
        if (condition) {
            this.viewContainer.createEmbeddedView(this.templateRef);
            //if the condition is true create a view
        } else {
            this.viewContainer.clear();
            //otherwise destroy it
        }
    }
}

We will create and destroy elements in the DOM using templateRef and viewContainer.

app.module.ts

import { MyCustomIfDirective } from './myCustomIf.directive';

@NgModule({
  declarations: [ MyCustomIfDirective ]
})
export class AppModule { }

Next we have to import this directive into the respective component module to use it.

app.component.html

<h2 *myCustomIf="condition">Hello {{name}}</h2>
<button (click)="condition = !condition">Click to toggle!</button>

Here we have used the custom structural directive as myCustomIf. It just toggles the DOM and it will render the view for us.

Structural Directive demo => https://bit.ly/38cmm9Z

Conclusion

So which is better? Structural or Attribute directive?

It totally depends on your requirements. Basically if you want to do some styling changes or if you want to get a value from a view then you can go for Attribute directives. If you want to create and destroy elements in the DOM go for Stuctural directives.

Choose the right directive at the right place!

In our next blog, we will see about Angular Interceptors.

Happy Coding!

Cheers! 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Blog at WordPress.com.

Up ↑

%d bloggers like this: