Directives

This is a short introduction to get you start and experience with Angular. For more information, please refer to Angular.io.

(Please tell me if you find any errors or omissions in the document, 3-April-2021)

Overview

  What are directives?  

  • Directives are JavaScript classes and declared as @directive
  • Directives describe Angular-specific HTML attributes that give dynamic behavior
  • Directives tell Angular to attach a specified behavior to the associated DOM element
  • Three types of directives:
    • Component directives
      • Directives with templates (note: templates describe views)
      • Describe how the component should be processed, instantiated, and used at runtime
    • Structural directives
      • Manipulate the structure of the DOM element
      • Start with a * sign; for example, *ngIf, *ngSwitch, and *ngFor
      • Affect the entire portion in the DOM
    • Attribute directives
      • Change the appearance and behavior of the DOM elements; for example, ngStyle and ngClass
      • Used in data binding and event binding
      • Affect only the associted element
  • This brief overview introduces some commonly used Angular built-in directives. In addition to the built-in directives, custom directives for specific behavior can be created using
    • ng generate directive directive-name or
    • ng g directive directive-name
Note: Directives are case sensitive.

NgModule

  • TypeScript class decorated with the @NgModule decorator, imported from the @angular/core package
  • Organize code — components, directives, services, routing mechanisms
  • Each Angular app has at least one module, called the root module or AppModule (by convention)
  • To create a module,
    • ng generate module module-name or
    • ng g module module-name

ngIf

  • Display or hide an element based on a condition
  • The condition is determined by the result of the expression that is passed into the directive.
  • If the result of the expression returns a false value, the element will be removed from the DOM.
  • Syntax: *ngIf="condition-or-boolean-expression"
  • Example:
    <div *ngIf="orderForm.value.name=='demo'">display when name is 'demo'</div>
    <div *ngIf="a > b">display if a is more than b</div>
    <div *ngIf="str == 'yes'">displayed if str is the string 'yes'</div>
    <div *ngIf="myfunc()">displayed if myfunc() returns true</div>  

ngSwitch

  • Render different elements depending on a give condition; for instance, when using ngIf several times
  • Syntax: *ngSwitchCase="case-value"
  • Example:
    <div class="container">
      <div *ngIf="myVar == 'A'">Var is A</div>
      <div *ngIf="myVar == 'B'">Var is B</div>
      <div *ngIf="myVar != 'A' && myVar != 'B'">Var is something else</div>
    </div>  
    can be transformed into
    <div class="container" [ngSwitch]="myVar">
      <div *ngSwitchCase="'A'">Var is A</div>
      <div *ngSwitchCase="'B'">Var is B</div>
      <div *ngSwitchDefault>Var is something else</div>
    </div>  
  • [ngSwitch] captures the value of myVar variable
  • Use ngSwitchCase directive to describe the known cases (or results)
  • Use ngSwitchDefault to handle all the other unknown cases. Note: ngSwitchDefault is optional.

ngFor

  • Repeat a given DOM element (or a collection of DOM elements) and pass an element of the array on each iteration
  • Syntax: *ngFor="let item of item-collection"
    The let item specifies a (template) variable that is receiving each element of the item-collection array. The item-collection is the collection of items from the controller.
  • Example: assume there is an array of people objects in app.component.ts
    this.students = [
       { name: 'Mickey', email: 'mickey@uva.edu', major: 'CS', year: 'second' },
       { name: 'Minney', email: 'minney@uva.edu', major: 'CS', year: 'third' },
       { name: 'duh', email: 'duh@uva.edu', major: 'SWE', year: 'third' },
       { name: 'huh', email: 'huh@uva.edu', major: 'SWE', year: 'second' }
    ];  
    Each row of data can be rendered as a table in app.component.html
    <h4>List of students</h4>
    <table>
      <thead>
        <tr>
          <th>Name</th>
          <th>Email</th>
          <th>Major</th>
          <th>Year</th>
        </tr>
      </thead>
      <tr *ngFor="let s of students">
        <td>{{ s.name }}</td>
        <td>{{ s.email }}</td>
        <td>{{ s.major }}</td>
        <td>{{ s.year }}</td>
    </table>
    
  • Another example:
    this.studentsByMajor = [
       {
          major: 'CS',
          students: [
             { name: 'Mickey', email: 'mickey@uva.edu', year: 'second' },
             { name: 'Minney', email: 'minney@uva.edu', year: 'second' },
          ] 
       },
       {
          major: 'SWE',
          students: [ 
             { name: 'duh', email: 'duh@uva.edu', year: 'third' },
             { name: 'huh', email: 'huh@uva.edu', year: 'second' }
          ]   
       }
    ];  
    A nested directive may be used to iterate through the students for a given major.
    <h4>List of students by major<h4>
    <div *ngFor="let m of studentsByMajor">
      <h2>{{ m.major }}</h2>
      <table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Email</th>       
            <th>Year</th>
          </tr>
        </thead>
        <tr *ngFor="let s of students">
          <td>{{ s.name }}</td>
          <td>{{ s.email }}</td>
          <td>{{ s.year }}</td>
        </tr>
      </table>  
    </div>
    

ngStyle

  • Set a given DOM element CSS properties from Angular expressions
  • Two ways to use this directive:
    • [style.cssproperty]="value"
      Example
      <div [style.background-color]="'blue'" [style.color]="'white'">
        Use fixed white text on blue background 
      </div>  
    • [ngStyle]="{'cssproperty': 'value', 'anotherproperty': 'value'}"
      Example
      <div [ngStyle]="{'background-color': 'blue', 'color': 'white'}">
        Use fixed white text on blue background 
      </div>  
  • Example: setting color and font size based on input values
    • View in app.component.html
      <div>
        <input type="text" name="color" value="{{color}}" #colorinput>
      </div>
      <div>
        <input type="text" name="fontSize" value="{{fontSize}}" #fontinput>
      </div>
      <button (click)="apply(colorinput.value, fontinput.value)">
        Apply settings
      </button>
      
      <div>
        <span [ngStyle]="{'color': color, 'font-size.px': fontSize}">  
          {{color}} text
        </span>
      </div>   
    • The apply method (that sets the new color and font size values) in class declaration in app.component.ts
      color = 'black';     /* set default */
      fontSize = 12;       /* set default */
      apply(color: string, fontSize: number): void {
         this.color = color;
         this.fontSize = fontSize;
      }  

ngClass

  • Dynamically set and change the CSS classes for a given DOM element
  • To use this directive, passing in an object literal
  • The object has the keys as the class names and the values are a boolean value indicating whether the class should be applied or not.
  • [ngClass]="{cssproperty: booelean-value}"
  • Example: a class selector in app.component.css
    .bordered { 
       border: 1px dashed black;
       background-color: #eee; 
    }  
    and a view in app.component.html
    <div [ngClass]="{bordered: false}">This is never bordered</div>
    <div [ngClass]="{bordered: true}">This is always bordered</div>