Skip to main content

Directives

January 30, 2024About 3 min

Directives

  • A directive is essentially a function that executes whenever the Angular compiler finds it in the Template
  • Directives are used to extend the power of the HTML by adding new syntax
  • A component is therefore a (more advanced) directive

Example

  • The following StackBlitz example contains the most common directives:

Structural directives

  • Structural directives are used to manipulate the DOM
  • They shape or reshape the DOM's structure, typically by adding, removing, or manipulating elements
  • Easy recognizable by the asterisk (*) prefix
structural directiveexamplepurpose
@if@if(showFirstDiv) { ... }Takes a boolean expression and makes an entire chunk of the DOM appear or disappear (NOT hidden)
@else@else { ... }If the boolean expression returns false we add a the HTML within the else block
@for@for (n of names; track $index) { ... }Adds the element(s) within the @for n-times to the DOM based on the amount of items in the list. The block of HTML acts as a template for rendering each item in the list
@for (n of names; track $index; let i = $index,isFirst = $first, isLast = $last) { ... }Values we can use as local variables withing the @for : index, count, first, last, even, odd

@if: why removing instead of hiding?

  • When the boolean expression in the @if directive returns false, the entire element is removed from the DOM
  • Hiding the element would mean that all the bindings and events still exist, although the element is invisible
  • This requires extra (unnecessary) resources from Angular (and thus the browser), which could slow down the application

@for aliases

  • Within the @for directive we can access some values which could be interesting to know because we are working with an iteration
  • These values can be aliased to local variables
    • let i = $index;: index is the value, i is the local variable
    • let isFirst = $first: first is the value, isFirst is the local variable
    • ...

@for : track $index

Track is a feature that helps Angular identify unique items in a collection, allowing it to track changes more efficiently and re-render only the elements that have been modified.

Track really comes into play when looping more complex objects, but we just add it by default right now!

Attribute directives

  • Attribute directives listen to and modify the behavior of other HTML elements, attributes, properties, and components

@switch

  • The @switch directive is actually a set of cooperating directives: switch, case, and default
<div>
      @switch (color) { 
        @case ('green') {
          <div class="green">GREEN</div>
        } 
        @case ('red') {
          <div class="red">RED</div>
        } 
        @case ('blue') {
          <div class="blue">BLUE</div>
        } 
        @default{
          <div class="gray">DEFAULT</div>
        } 
      }
</div>
  • @switch accepts a property or a expression
  • @case checks its value against the @switch value and returns the HTML when they are a match

single quotes in an expression

  • There is a difference when using single quotes or not in an expression
  • @case('green'): expression is just the string green
  • @case(green): expression is the property green

[ngClass]

  • Add or remove several CSS classes simultaneously
  • Based on a boolean property : isSpecial
<div [ngClass]="isSpecial ? 'special' : ''">This div is special</div>
  • Based on an object of classes : currentClasses
<div [ngClass]="currentClasses">Current classes div</div>
  • Component class file
isSpecial: boolean = true;

currentClasses: {};
isLarge: boolean = true;
isError: boolean = false;

setCurrentClasses() {
    // CSS classes based on business logic
    this.currentClasses = {
      large: this.isLarge,
      error: this.isError
    };
}
 

 





 
 
 
 

  • CSS
.special {
  border: 2px dotted red;
}

.large {
  font-size: 2rem;
}

.error {
  color: red;
  background-color: rgba(255, 0, 0, 0.1);
}

Add/remove single class

  • To add or remove a single class, use class binding rather than NgClass
  • [class.sale]="onSale" : adds sale class to element if onSale expression is true

[ngStyle]

  • Set many inline styles simultaneously and dynamically, based on the state of the component
<div [ngStyle]="currentStyles">Current styles div</div>
currentStyles: {};
isItalic: boolean = true;
isBold: boolean = false;

setCurrentStyles() {
    // CSS inline styles based on business logic
    this.currentStyles = {
      "font-style": this.isItalic ? "italic" : "normal",
      "font-weight": this.isBold ? "bold" : "normal"
    };
}
 





 
 
 
 

A component is a directive

  • A component is a directive
  • This makes perfect sense because a component is loaded when defining the selector as an HTML element in the template
    • We are extending the power of the HTML, because we add a complete new set of elements to the DOM
  • Therefore a component is a directive with a template

Want proof? Check the source code!

  • Go to the node_module\@angular\core\index.d.ts file and check the declaration of the Component interface (line 1436):
/**
 * Supplies configuration metadata for an Angular component.
 *
 * @publicApi
 */
export declare interface Component extends Directive {
    /**
     * The change-detection strategy to use for this component.
     *
     * When a component is instantiated, Angular creates a change detector,
     * which is responsible for propagating the component's bindings.
     * The strategy is one of:
     * - `ChangeDetectionStrategy#OnPush` sets the strategy to `CheckOnce` (on demand).
     * - `ChangeDetectionStrategy#Default` sets the strategy to `CheckAlways`.
     */
    changeDetection?: ChangeDetectionStrategy;
    ...





 











  • The Component interface extends a directive interface

Check it yourself

  • Check the news app and find out where we already implemented some of these directives

Exercise

Building on the stackblitz above implement the following features.

  • Add a checkbox that binds to the showSecondDiv property so you can change this
  • Create a dropdown that binds to the color property with options "green" and "blue"