Attribute Directives

Go back to Tutorial

Attribute directives are a way of changing the appearance or behavior of a component or a native DOM element. Ideally, a directive should work in a way that is component agnostic and not bound to implementation details. Attribute directives actually modifies the appearance or behavior of an element. The attribute directive changes the appearance or behavior of a DOM element. These directives look like regular HTML attributes in templates. The ngModel directive which is used for two-way binding is an perfect example of an attribute directive. For create attribute directives, we always need to use or inject the below objects in our custom attribute directive component class.

Build a simple attribute directive

An attribute directive minimally requires building a controller class annotated with @Directive, which specifies the selector that identifies the attribute. The controller class implements the desired directive behavior.

This page demonstrates building a simple appHighlight attribute directive to set an element’s background color when the user hovers over that element. You can apply it like this:

src/app/app.component.html (applied)

<p appHighlight>Highlight me!</p>

Write the directive code – Create the directive class file in a terminal window with this CLI command.

ng generate directive highlight

The CLI creates src/app/highlight.directive.ts, a corresponding test file (…/spec.ts, and declares the directive class in the root AppModule.

Directives must be declared in Angular Modules in the same manner as components. The generated src/app/highlight.directive.ts is as follows:

src/app/highlight.directive.ts

import { Directive } from ‘@angular/core’;

@Directive({

selector: ‘[appHighlight]’

})

export class HighlightDirective {

constructor() { }

}

The imported Directive symbol provides the Angular the @Directive decorator. The @Directive decorator’s lone configuration property specifies the directive’s CSS attribute selector, [appHighlight].

It’s the brackets ([]) that make it an attribute selector. Angular locates each element in the template that has an attribute named appHighlight and applies the logic of this directive to that element. The attribute selector pattern explains the name of this kind of directive.

Though highlight would be a more concise selector than appHighlight and it would work, the best practice is to prefix selector names to ensure they don’t conflict with standard HTML attributes. This also reduces the risk of colliding with third-party directive names. The CLI added the app prefix for you.

Make sure you do not prefix the highlight directive name with ng because that prefix is reserved for Angular and using it could cause bugs that are difficult to diagnose.

After the @Directive metadata comes the directive’s controller class, called HighlightDirective, which contains the (currently empty) logic for the directive. Exporting HighlightDirective makes the directive accessible. Now edit the generated src/app/highlight.directive.ts to look as follows:

src/app/highlight.directive.ts

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

@Directive({

selector: ‘[appHighlight]’

})

export class HighlightDirective {

constructor(el: ElementRef) {

el.nativeElement.style.backgroundColor = ‘yellow’;

}

}

The import statement specifies an additional ElementRef symbol from the Angular core library:

You use the ElementRef in the directive’s constructor to inject a reference to the host DOM element, the element to which you applied appHighlight.

ElementRef grants direct access to the host DOM element through its nativeElement property.

This first implementation sets the background color of the host element to yellow.

Apply the attribute directive

To use the new HighlightDirective, add a paragraph (<p>) element to the template of the root AppComponent and apply the directive as an attribute.

src/app/app.component.html

<p appHighlight>Highlight me!</p>

Now run the application to see the HighlightDirective in action.

ng serve

To summarize, Angular found the appHighlight attribute on the host <p> element. It created an instance of the HighlightDirective class and injected a reference to the <p> element into the directive’s constructor which sets the <p> element’s background style to yellow.

Respond to user-initiated events

Currently, appHighlight simply sets an element color. The directive could be more dynamic. It could detect when the user mouse into or out of the element and respond by setting or clearing the highlight color.

Begin by adding HostListener to the list of imported symbols.

src/app/highlight.directive.ts (imports)

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

Then add two eventhandlers that respond when the mouse enters or leaves, each adorned by the HostListener decorator.

src/app/highlight.directive.ts (mouse-methods)

@HostListener(‘mouseenter’) onMouseEnter() {

this.highlight(‘yellow’);

}

@HostListener(‘mouseleave’) onMouseLeave() {

this.highlight(null);

}

private highlight(color: string) {

this.el.nativeElement.style.backgroundColor = color;

}

The @HostListener decorator lets you subscribe to events of the DOM element that hosts an attribute directive, the <p> in this case.

Of course you could reach into the DOM with standard JavaScript and attach event listeners manually. There are at least three problems with that approach:

  • You have to write the listeners correctly.
  • The code must detach the listener when the directive is destroyed to avoid memory leaks.
  • Talking to DOM API directly isn’t a best practice.

The handlers delegate to a helper method that sets the color on the host DOM element, el.

The helper method, highlight, was extracted from the constructor. The revised constructor simply declares the injected el: ElementRef.

src/app/highlight.directive.ts (constructor)

constructor(private el: ElementRef) { }

Here’s the updated directive in full:

src/app/highlight.directive.ts

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

@Directive({

selector: ‘[appHighlight]’

})

export class HighlightDirective {

constructor(private el: ElementRef) { }

@HostListener(‘mouseenter’) onMouseEnter() {

this.highlight(‘yellow’);

}

@HostListener(‘mouseleave’) onMouseLeave() {

this.highlight(null);

}

private highlight(color: string) {

this.el.nativeElement.style.backgroundColor = color;

}

}

Run the app and confirm that the background color appears when the mouse hovers over the p and disappears as it moves out.

Go back to Tutorial

Share this post
[social_warfare]
Component or Directives
Built-in Directives

Get industry recognized certification – Contact us

keyboard_arrow_up