Attribute directives

From Get docs
Angular/docs/11/guide/attribute-directives


Attribute directives

With attribute directives, you can change the appearance or behavior of DOM elements and Angular components.

See the live example for a working example containing the code snippets in this guide.

Building an attribute directive

This section walks you through creating a highlight directive that sets the background color of the host element to yellow.

  1. To create a directive, use the CLI command ng generate directive.

    ng generate directive highlight

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

    The CLI generates the default src/app/highlight.directive.ts as follows:

    import { Directive } from '@angular/core';
    
    @Directive({
      selector: '[appHighlight]'
    })
    export class HighlightDirective {
      constructor() { }
    }

    The @Directive() decorator's configuration property specifies the directive's CSS attribute selector, [appHighlight].

  2. Import ElementRef from @angular/core. ElementRef grants direct access to the host DOM element through its nativeElement property.

  3. Add ElementRef in the directive's constructor() to inject a reference to the host DOM element, the element to which you apply appHighlight.

  4. Add logic to the HighlightDirective class that sets the background to yellow.

    import { Directive, ElementRef } from '@angular/core';
    
    @Directive({
      selector: '[appHighlight]'
    })
    export class HighlightDirective {
        constructor(el: ElementRef) {
           el.nativeElement.style.backgroundColor = 'yellow';
        }
    }

Directives do not support namespaces.

<p app:Highlight>This is invalid</p>

Applying an attribute directive

  1. To use the HighlightDirective, add a <p> element to the HTML template with the directive as an attribute.

    <p appHighlight>Highlight me!</p>

Angular creates an instance of the HighlightDirective class and injects a reference to the <p> element into the directive's constructor, which sets the <p> element's background style to yellow.

Handling user events

This section shows you how to detect when a user mouses into or out of the element and to respond by setting or clearing the highlight color.

  1. Import HostListener from '@angular/core'.

    import { Directive, ElementRef, HostListener } from '@angular/core';
  2. Add two event handlers that respond when the mouse enters or leaves, each with the @HostListener() decorator.

    @HostListener('mouseenter') onMouseEnter() {
      this.highlight('yellow');
    }
    
    @HostListener('mouseleave') onMouseLeave() {
      this.highlight(null);
    }
    
    private highlight(color: string) {
      this.el.nativeElement.style.backgroundColor = color;
    }

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

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

The complete directive is as follows:

@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;
  }

}

The background color appears when the pointer hovers over the paragraph element and disappears as the pointer moves out.

Passing values into an attribute directive

This section walks you through setting the highlight color while applying the HighlightDirective.

  1. In highlight.directive.ts, import Input from @angular/core.

    import { Directive, ElementRef, HostListener, Input } from '@angular/core';
  2. Add an appHighlight @Input() property.

    @Input() appHighlight: string;

    The @Input() decorator adds metadata to the class that makes the directive's appHighlight property available for binding.

  3. In app.component.ts, add a color property to the AppComponent.

    export class AppComponent {
      color = 'yellow';
    }
  4. To simultaneously apply the directive and the color, use property binding with the appHighlight directive selector, setting it equal to color.

    <p [appHighlight]="color">Highlight me!</p>

    The [appHighlight] attribute binding performs two tasks:

    • applies the highlighting directive to the <p> element
    • sets the directive's highlight color with a property binding

Setting the value with user input

This section guides you through adding radio buttons to bind your color choice to the appHighlight directive.

  1. Add markup to app.component.html for choosing a color as follows:

    <h1>My First Attribute Directive</h1>
    
    <h2>Pick a highlight color</h2>
    <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>
  2. Revise the AppComponent.color so that it has no initial value.

    export class AppComponent {
      color: string;
    }
  3. Serve your application to verify that the user can choose the color with the radio buttons.

Binding to a second property

This section guides you through configuring your application so the developer can set the default color.

  1. Add a second Input() property to HighlightDirective called defaultColor.

    @Input() defaultColor: string;
  2. Revise the directive's onMouseEnter so that it first tries to highlight with the highlightColor, then with the defaultColor, and falls back to red if both properties are undefined.

    @HostListener('mouseenter') onMouseEnter() {
      this.highlight(this.highlightColor || this.defaultColor || 'red');
    }
  3. To bind to the AppComponent.color and fall back to "violet" as the default color, add the following HTML. In this case, the defaultColor binding doesn't use square brackets, [], because it is static.

    <p [appHighlight]="color" defaultColor="violet">
      Highlight me too!
    </p>

    As with components, you can add multiple directive property bindings to a host element.

The default color is red if there is no default color binding. When the user chooses a color the selected color becomes the active highlight color.

Deactivating Angular processing with NgNonBindable

To prevent expression evaluation in the browser, add ngNonBindable to the host element. ngNonBindable deactivates interpolation, directives, and binding in templates.

In the following example, the expression Template:1 + 1 renders just as it does in your code editor, and does not display 2.

<p>Use ngNonBindable to stop evaluation.</p>
<p ngNonBindable>This should not evaluate: {{ 1 + 1 }}</p>

Applying ngNonBindable to an element stops binding for that element's child elements. However, ngNonBindable still allows directives to work on the element where you apply ngNonBindable. In the following example, the appHighlight directive is still active but Angular does not evaluate the expression Template:1 + 1.

<h3>ngNonBindable with a directive</h3>
<div ngNonBindable [appHighlight]="'yellow'">This should not evaluate: {{ 1 +1 }}, but will highlight yellow.
</div>

If you apply ngNonBindable to a parent element, Angular disables interpolation and binding of any sort, such as property binding or event binding, for the element's children.

© 2010–2021 Google, Inc.
Licensed under the Creative Commons Attribution License 4.0.
https://v11.angular.io/guide/attribute-directives