Angular 2 Built-in Directives

See how Angular uses the ngIf, ngSwitch, ngFor, ngClass and ngStyle directives to transform the DOM when a template is rendered.

Updated Jan 2017, Angular version 2.4.x

Directives

You can learn about each of the built-in directives by clicking the links below, or see them in action in the example which follows.

  • ngIf adds and removes elements in the DOM based on the results of an expression.
  • ngSwitch displays one element (and its children) from a set of possible options, based on some condition.
  • ngFor is a repeater directive which outputs a list of elements by iterating over an array.
  • ngClass adds and removes CSS classes on an element.
  • ngStyle sets CSS styles on an HTML element conditionally.

Example

Let's take look at this simple voting app which makes use of the built-in directives.

The first ngFor directive iterates over a list of candidates which are retrieved from a service. The candidate name is used as the button label, and index identifies the candidates position in the array when a button is clicked.

The second ngFor displays the colored blocks by looping over an array which is initialized with the number of votes for each candidate. The color of the blocks is determined by an ngClass directive. The template expression in quotes returns first, last or other which correspond to the class names in the styles property.

We use ngStyle to change the appearance of the leading candidates vote count. When the candidate is winning then the font-weight is changed to bold.

Finally, when we move the mouse over the colored blocks we display some additional information about the candidate. Here we use an ngSwitch directive to determine which message should be display.

voter.component.ts
import { Component } from '@angular/core';
import { CandidateService, Candidate, Position } from './candidate-service'

@Component({
    selector: 'voter',
    template:  `
        <p *ngFor="let candidate of candidates.all, let i=index">
            <button (click)="vote(i)" >{{candidate.name}}</button>
            <span *ngFor="let block of blocks(i)" 
                  [innerHTML]="'&#9609;'" 
                  class="hover"
                  [ngClass]="blockStyle(i)"
                  (mouseover)="hover(i)"
                  (mouseleave)="hover()">
            </span>
            <span [ngStyle]="numberStyle(candidate)">{{candidate.count}}</span>
        </p>
        
        <div *ngIf="hoverOver">
            <div [ngSwitch]="hoverOver.position">
                <h1 *ngSwitchCase="Position.FIRST">{{hoverOver.name}} is winning!</h1>
                <h3 *ngSwitchCase="Position.LAST">{{hoverOver.name}} is losing</h3>
                <h2 *ngSwitchDefault>{{hoverOver.name}} has {{hoverOver.count}} votes</h2>
            </div>
        </div>`,
    styles: [`
        button { width: 50px; height: 27px; }
        .hover { cursor: pointer } 
        .first { color: LightGreen; }
        .last { color: Red; }
        .other { color: Gray; }`
    ],
    providers: [CandidateService]
})
export class VoterComponent {

    private hoverOver: Candidate = null;
    private Position: any = Position;

    constructor(private candidates: CandidateService) {};

    private blockStyle(index: number) {
        return Position.toString(this.candidates.getOne(index).position);
    }

    private numberStyle(candidate: Candidate): any {
        return {
            'font-size' : '20px',
            'font-weight' : candidate.position == Position.FIRST ? 'bold' : 'normal'
        }
    }

    private vote(index: number) {
        this.candidates.vote(index);
    }

    private blocks(index: number) {
        return new Array(this.candidates.getOne(index).count);
    }

    private hover(index: number = null): void {
        this.hoverOver = index == null ? null : this.candidates.getOne(index);
    }
}

Showing and Hiding Elements

There are several ways to show and hide elements on a page. Let's look at a few of them.

ngIf adds or removes an element subtree (an element and its children) in the DOM. In this example, the parent div has zero children when ngIf is false. Try it yourself in the application below.

When we set the hidden property to a truthy value, the element is hidden but remains in the DOM. The same is true when display is set to none using a style binding.

Setting the visibility style to hidden also hides the element but still takes up space on the page.

show-and-hide.component.ts
import { Component } from "@angular/core";

@Component({
    selector: 'ng-if-directive',
    template: `
        <h2>Show and Hide Elements</h2>
        <hr/>
        
        <p>
            ngIf condition is {{addToDom ? 'true' : 'false'}}    
            <button (click)="addToDom=!addToDom">set to {{addToDom ? 'false' : 'true'}}</button>
        </p>
        <div #div1>
            <h3 *ngIf="addToDom" >This heading is added to and removed from the DOM</h3>
        </div>
        <p>Children: {{div1.children.length}}, content: '{{div1.children[0]?.innerText}}'</p>
        <hr/>

        <p>
            hidden value is {{hidden ? 'true' : 'false'}}
            <button (click)="hidden=!hidden">set to {{hidden ? 'false' : 'true'}}</button>
        </p>
        <div #div2>
            <h3 [hidden]="hidden">This heading can be hidden but remains in the DOM</h3>
            <h3 [style.display]="hidden ? 'none' : 'block'">and this one too</h3>
        </div>
        <p>Children: {{div2.children.length}}, content: '{{div2.children[0].innerText}}', '{{div2.children[1].innerText}}'</p>
        <hr/>
        
        <p>
            CSS visible value is {{visible}} 
            <button (click)="visible=!visible">set to {{visible ? 'false' : 'true'}}</button>
        </p>
        <div #div3>
            <h3 [style.visibility]="visible ? 'visible' : 'hidden'">
                This heading remains in the DOM but the text is invisible
            </h3>
        </div>
        <p>Children: {{div3.children.length}}, content: '{{div3.children[0].innerText}}'</p>`
})
export class ShowAndHideComponent {
    private addToDom: boolean = true;
    private hidden: boolean = false;
    private visible: boolean = true;
}

The Application

See the effects of showing and hiding elements on the page.

Where Next?

To find out more about Angular and TypeScript, check out these tutorials.

  • Hello World - Implement a super-simple <hello-world> custom element using an Angular and TypeScript.
  • The Angular with TypeScript Tutorial - includes examples of components, template syntax, property binding, event binding, bootstrapping and more.
  • Configuration - Configure Angular and TypeScript to download dependencies from node modules or a CDN, and to compile the TypeScript during development or in the browser at runtime.
  • Templates - introduction to inline and external templates.
  • Interpolation - use curly braces and template expressions to output data on the page.
  • Property Binding - bind to DOM properties using square brackets and template expressions.
  • Event Binding - handle DOM events using parentheses and template statements.
  • Two-way Binding - combine property and event binding to create two-way binding with ngModel.
  • Input Binding - bind to <input> fields such as text, textarea, checkbox, radio and select.
  • Component Input Output - use @Input and @Output to pass data in to and out of a component.
  • Angular Router - Use the Angular router to navigate between components when the user clicks a link.
  • Nested Child Routes - An example of how child routes allow navigation between multiple views when a user clicks a link in a sub-menu.