Categories
Angular JavaScript

Defining and Using Angular Attribute Directives

Spread the love

Angular is a popular front-end framework made by Google. Like other popular front-end frameworks, it uses a component-based architecture to structure apps.

In this article, we’ll look at how to create and use attribute directives with Angular.

Build a Simple Attribute Directive

We can create a simple directive by using the Angular CLI.

To create one, we run:

ng generate directive highlight

to create the skeleton code for our directive.

Once we did that, we can write some code for our directive. We write the following code:

highlight.directive.ts :

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

@Directive({  
  selector: '[appHighlight]'  
})  
export class HighlightDirective {  
  constructor(el: ElementRef) {  
    el.nativeElement.style.backgroundColor = 'pink';  
  }  
}

The code above takes an ElementRef of the element that the directive is applied to.

Then we set the backgroundColor of it to 'pink' .

The bracket makes our directive an attribute directive.

We should prefix our directive names with something like app so that they don’t clash with HTML attribute names.

app.module.ts :

import { BrowserModule } from '@angular/platform-browser';  
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';  
import { AppComponent } from './app.component';  
import { HighlightDirective } from './highlight.directive';

@NgModule({  
  declarations: [  
    AppComponent,  
    HighlightDirective  
  ],  
  imports: [  
    BrowserModule,  
    AppRoutingModule  
  ],  
  providers: [],  
  bootstrap: [AppComponent]  
})  
export class AppModule { }

We added HighlightDirective to our AppModule so we can use it.

Then we can use it in app.component.html as follows:

<div appHighlight>foo</div>

We then should see a pink div with ‘foo’ inside it.

Respond to User-Initiated Events

We can also use directives to detect and act on user-initialed events.

For example, we can write the change the HighlightDirective we had above as follows:

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

@Directive({  
  selector: '[appHighlight]'  
})  
export class HighlightDirective {  
  constructor(private el: ElementRef) {    } 

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

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

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

We added the HostListener decorators to listen to the mouseenter and mouseleave events of the element that our highlight directive is applied to.

Therefore, when we hover over our text, we’ll see it turn pink. Otherwise, it’ll go back to its normal color.

Pass Values Into the Directive with an @Input Data Binding

We can use the @Input decorator as we do with components to pass data to directives.

For example, we can write the following:

highlight.directive.ts :

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

@Directive({  
  selector: '[appHighlight]'  
})  
export class HighlightDirective {  
  @Input() highlightColor: string;  
  constructor(private el: ElementRef) { } 

  ngOnInit() {  
    this.el.nativeElement.style.color = this.highlightColor;  
  }  
}

app.component.html :

<div appHighlight highlightColor='pink'>foo</div>

In the code above, we added the highlightColor input and then pass in the color string in app.component.html to set the color.

We’ll then get pink text since we set highlightColor to pink.

Bind to an @Input Alias

We can make the code above shorter if we change the @Input alias to have the same name as the directive name.

For example, we can write:

highlight.directive.ts :

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

@Directive({  
  selector: '[appHighlight]'  
})  
export class HighlightDirective {  
  @Input('appHighlight') highlightColor: string;  
  constructor(private el: ElementRef) { } 

  ngOnInit() {  
    this.el.nativeElement.style.color = this.highlightColor;  
  }  
}

Then we can use it as follows in app.component.html ;

<div appHighlight='pink'>foo</div>

As we can see, we don’t have to specify highlightColor separately anymore.

Bind to a Second Property

We can have multiple @Input s to bind to multiple properties.

For example, we can write the following:

highlight.directive.ts :

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

@Directive({  
  selector: '[appHighlight]'  
})  
export class HighlightDirective {  
  @Input('appHighlight') highlightColor: string;  
  @Input() defaultColor: string;  
  constructor(private el: ElementRef) { } 

  ngOnInit() {  
    this.el.nativeElement.style.color = this.highlightColor || this.defaultColor;  
  }  
}

In the code above, we have 2 @Inputs instead of one.

Now we can use it as follows in app.component.html :

<div appHighlight='pink' defaultColor='yellow'>foo</div>  
<div appHighlight defaultColor='green'>bar</div>

In the code above, we have appHighlight directive applied without any color string set in the second div.

Therefore, since defaultColor is set to 'green' , it’ll be applied as we specified in highlight.directive.ts ‘s ngOnInit method.

Conclusion

We define attribute directives by running ng g directive and name them with brackets outside the name.

Then we can pass in properties with @Input s and listen to events with @HostListener .

Also, we get the element that the directive is applied to and then apply whatever styles we want to it.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

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