Angular
Angular Directives

Attribute Directives

PRO

Attribute directives are surrounded by brackets which signals to Angular that the appearance or behavior of the DOM elements within the directive may change depending on certain conditions.

For example:

<h1>My First Attribute Directive</h1>

<h4>Pick a highlight color</h4>
<div>
  <input type="radio" name="colors" (click)="color='lightgreen'" />Green
  <input type="radio" name="colors" (click)="color='yellow'" />Yellow
  <input type="radio" name="colors" (click)="color='cyan'" />Cyan
</div>
<p [appHighlight]="color">Highlight me!</p>

In this template, we have an appHighlight attribute directive that is bound to the color property. When a user clicks on the radio buttons, Angular sets the value of color to the values shown in the template.

Here's the code for the attribute directive:

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

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {

  constructor(private el: ElementRef) { }

  @Input('appHighlight') highlightColor: string;

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

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

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

You can view the entire sample and explanation on the Angular Docs

Let's take a look at how to create another directive. In this example, we'll be making an attribute directive that bolds text when it is hovered over.

app/bold-hover.directive.ts

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

@Directive()
export class BoldHoverDirective {
  private element: HTMLElement;

  constructor(elementRef: ElementRef){
    this.element = elementRef.nativeElement;
  }
}

ElementRef provides us with a way of getting a reference to the DOM element that the directive is attatched to using the nativeElement property. We're saving a reference to the element in a private variable called element. Directive is the decorator used for configuring directives, which we'll be using in the next steps. Just like with configuring components, we'll need to define a selector which will tell Angular how to identify the directive that needs to be used. We can also provide a host object for binding events from that elements to functions on our directive

Next we'll configure the selector and host properties for our @Directive() decorator:

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

@Directive({
  selector: '[boldHover]'
})
export class BoldHoverDirective {
  private element: HTMLElement;

  constructor(element: ElementRef){
    this.element = element.nativeElement;
  }
}

Now our directive can be used in templates by adding boldHover as an element attribute like <p boldHover>I turn bold when hovered</p>

Next lets create the onMouseEnter and onMouseLeave methods for our directive:

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

@Directive({
  selector: '[boldHover]',
  host: {
    '(mouseenter)': 'onMouseEnter()',
    '(mouseleave)': 'onMouseLeave()'
  }
})
export class BoldHoverDirective {
  private element: HTMLElement;

  constructor(element: ElementRef){
    this.element = element.nativeElement;
  }

  onMouseEnter() {
    this.element.style.fontWeight = 'bold';
  }
  onMouseLeave() {
    this.element.style.fontWeight = 'normal';
  }
}

Now our directive is ready to be used!

Lets import the directive we made into app/app.component.ts and register the directive in the @Component() decorator.

import { Component } from '@angular/core';
import { BoldHoverDirective } from './bold-hover.directive';

@Component({
  selector: 'my-app',
  template: '<p boldHover>I turn bold when hovered</p>',
  providers: [BoldHoverDirective]
})
export class AppComponent {}

You can view a live demo of this example here:

Now whenever we mouseover the text, it should turn bold!

Challenge: Before proceeding to the next chapter, try creating a structural directive that can display or remove the given element.

 

I finished! On to the next chapter