11. Structural Directives

Builtin Structural Directives:

<blockquote>
    <div *ngIf="technology">My {{ technology.name }}</div>
</blockquote>

<p>List of technologies</p>
    <ul>
        <li *ngFor="let technology of technologies">{{ technology.name }}</li>
    </ul>

<div [ngSwitch]="technology?.emotion">
     <app-happy-technology *ngSwitchCase="'happy'" [technology]="technology"></app-happy-technology>
     <app-awesome-technology *ngSwitchCase="'awesome'" [technology]="technology"></app-awesome-technology>
     <app-contemplative-technology *ngSwitchCase="'contemplative'" [technology]="technology"></app-contemplative-technology>
     <app-unknownkiller-technology *ngSwitchDefault [technology]="technology"></app-unknownkiller-technology>
</div>

NgIf:

        <p *ngIf="true">
            expression is true ngIf is true. this paragraph is in DOM.
          </p>
          <p *ngIf="false">
            expression is false ngIf is false. this paragraph is not in DOM.
          </p>
          <p [style.display]="'block'">expression sets display block. paragraph is visible.
          </p>
          <p [style.display]="'none'">expression sets display none. paragraph is hidden but still in DOM.
          </p>

Asterisk Prefix with Desugaring Process:

        <div *ngIf="myTechnology">{{ myTechnology.name }}</div>

        <div template="ngIf myTechnology">{{ myTechnology.name }}</div>

        <ng-template [ngIf]="myTechnology">
          <div>{{ myTechnology.name }}</div>
        </ng-template>

Inside ngFor:

    <div *ngFor="let technology of technologies; let i = index; let odd = odd; trackBy: trackById;"
    [class.odd]="odd">
    ({{ i }}) {{ technology.name }}
    </div>
    <hr>
    <div template="ngFor let technology of technologies; let i = index; let odd = odd; trackBy: trackById;"
    [class.odd]="odd">
    ({{ i }}) {{ technology.name }}
    </div>
    <hr>
    <ng-template ngFor let-technology [ngForOf]="technologies" let-i="index" let-odd="odd"
    [ngForTrackBy]="trackById">
     <div [class.odd]="odd">({{ i }}) {{ technology.name }}</div>
    </ng-template>

Inside NgSwitch Directives

Technology Switch Components:

import { Component, Input } from '@angular/core';

import { Technology } from './technology';

@Component({
  selector: 'app-happy-technology',
  template: `Wow. You like {{ technology.name }}. What a happy technology ... just like you.`
})
export class HappyTechnologyComponent {
  @Input() technology: Technology;
}
@Component({
  selector: 'app-awesome-technology',
  template: `You are as awesome as {{ technology.name }}. May the sun always shine over you.`
})
export class AwesomeTechnologyComponent {
  @Input() technology: Technology;
}
@Component({
  selector: 'app-contemplative-technology',
  template: `Are you as contemplative as {{ technology.name }}?`
})
export class ContemplativeTechnologyComponent {
  @Input() technology: Technology;
}
@Component({
  selector: 'app-unknownkiller-technology',
  template: `{{ message }}`
})
export class UnknownKillerTechnologyComponent {
  @Input() technology: Technology;
  get message() {
    return this.technology && this.technology.name ?
            `${this.technology.name} is strange and mysterious` : 'Are you feeling a view to a kill?';
  }
}

export const technologiesSwitchComponents = [
  HappyTechnologyComponent, AwesomeTechnologyComponent,
  ContemplativeTechnologyComponent, UnknownKillerTechnologyComponent
];

AppComponent NgSwitch desugared (1 chromebook && 1 pound of sugar for my Polymer Princess):

    <div *ngFor="let technology of technologies">{{ technology.name }}</div>

          <div [ngSwitch]="technology?.emotion">
            <app-happy-technology *ngSwitchCase="'happy'" [technology]="technology"></app-happy-technology>
            <app-awesome-technology *ngSwitchCase="'awesome'" [technology]="technology"></app-awesome-technology>
            <app-contemplative-technology *ngSwitchCase="'contemplative'" [technology]="technology"></app-contemplative-technology>
            <app-unknownkiller-technology *ngSwitchDefault [technology]="technology"></app-unknownkiller-technology>
          </div>

  <div [ngSwitch]="technology?.emotion">
      <app-happy-technology template="ngSwitchCase 'happy'" [technology]="technology"></app-happy-technology>
      <app-awesome-technology template="ngSwitchCase 'awesome'" [technology]="technology"></app-awesome-technology>
      <app-contemplative-technology template="ngSwitchCase 'contemplative'" [technology]="technology"></app-contemplative-technology>
      <app-unknownkiller-technology template="ngSwitchDefault" [technology]="technology"></app-unknownkiller-technology>
  </div>

    <div [ngSwitch]="technology?.emotion">
      <ng-template [ngSwitchCase]="'happy'">
        <app-happy-technology [technology]="technology"></app-happy-technology>
      </ng-template>
      <ng-template [ngSwitchCase]="'awesome'">
        <app-awesome-technology [technology]="technology"></app-awesome-technology>
      </ng-template>
      <ng-template [ngSwitchCase]="'contemplative'">
        <app-contemplative-technology [technology]="technology"></app-contemplative-technology>
      </ng-template>
      <ng-template ngSwitchDefault>
        <app-unknownkiller-technology [technology]="technology"></app-unknownkiller-technology>
      </ng-template>
    </div>

Let's have a look at the results in our Chromium Web Browser:

Template Tag:

            <p>Hip!</p>
            <ng-template>
            <p>Hip!</p>
            </ng-template>
            <p>Array!</p>

NgContainer:

            <p>
                I looked up
                <ng-container *ngIf="technology">
                and saw {{ technology.name }}. I greeted
                </ng-container>
                and continued coding.
            </p>
            <div>
                Pick your favorite technology
                (<label><input type="checkbox" checked (change)="showAwesome = !showAwesome">show
                awesome</label>)
            </div>
            <select [(ngModel)]="technology">
              <ng-container *ngFor="let tech of technologies">
                <ng-container *ngIf="showAwesome || tech.emotion !== 'awesome'">
                  <option [ngValue]="tech">{{ tech.name }} ({{ tech.emotion }})</option>
                </ng-container>
              </ng-container>
            </select>

Let's view the running application in our Browser:

Unless Directive, Structural Directive, Does Opposite of NgIf Directive:

import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';

@Directive({ selector: '[appUnless]'})
export class UnlessDirective {
  private hasView = false;

  @Input() set appUnless(condition: boolean) {
    if (!condition && !this.hasView) {
      this.viewContainer.createEmbeddedView(this.templateRef);
      this.hasView = true;
    } else if (condition && this.hasView) {
      this.viewContainer.clear();
      this.hasView = false;
    }
  }

    constructor(private templateRef: TemplateRef<any>,
                private viewContainer: ViewContainerRef) { }

}

AppComponent:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
        <h1>{{ title }}</h1>
          <div class="left">
            <p>
                The condition is currently
                <span [ngClass]="{ 'a': !condition, 'b': condition, 'unless': true }">
                {{ condition }}
                </span>
                <button (click)="condition = !condition" [ngClass]="{ 'a': condition, 'b': condition }">
                Toggle condition to {{ condition ? 'false' : 'true' }}
                </button>
            </p>
              <p *appUnless="condition" class="unless a">
                (A) this paragraph is displayed because condition is false.
              </p>
              <p *appUnless="!condition" class="unless b">
                (B) although the condition is true, this paragraph is displayed because
                appUnless is set to false.
              </p>
            <h4>UnlessDirective with Template</h4>
              <p *appUnless="condition">Show this sentence unless the condition is true.</p>
              <p template="appUnless condition" class="unless">
              (A) this paragraph is shown when condition is false.
              </p>
              <ng-template [appUnless]="condition">
                <p class="unless">
                (A) this paragraph is also only shown unless the condition is true.
                </p>
              </ng-template>
          </div>
          <div class="right">
            <img [src]="imageUrl" class="img-round" alt="princess image">
          </div>
  `,
  styles: [`
            h1 { font-weight: bold; }
            .unless { border: 3px solid; }
            p.unless { width: 500px; }
            button.a, span.a, .unless.a {
              color: red;
              border-color: gold;
              background-color: yellow;
              font-size: 140%;
            }
            button.b, span.b, .unless.b {
              color: black;
              border-color: green;
              background-color: light-green;
              font-size: 160%;
            }
    `]
})
export class AppComponent {
  title = 'Tour of Technologies';
  imageUrl = '../assets/polymer1.jpg-large';
  condition = false;
}

Let's view the results in Chromium:

NgContainer:

import { Component } from '@angular/core';

@Component({
  selector: 'app-technologies',
  template: `
        <div class="row">
          <div class="col-6">
          <h2>{{ title }}</h2>
          <app-panel>
          <ng-container class="header"><h1>Angular 5</h1></ng-container>
          <ng-container class="body">
          <h3>One Framework. Mobile & desktop.</h3>
          <p>Angular CLI. Tool, Scaffold, Build Maintain Angular Applications.</p>
          <p>Angular Material. Beautiful CSS optimized for Angular.</p>
          </ng-container>
          </app-panel>
        </div>
        <div class="col">
            <img class="w-100 p-3 rounded-circle" [src]="imageUrl" />
        </div>
      </div>
  `
})
export class TechnologiesComponent {
  title = 'List of Technologies';
  imageUrl = './assets/polymer1.jpg';

}

PanelComponent:

import { Component } from '@angular/core';

@Component({
  selector: 'app-panel',
  template: `
          <div class="card text-white bg-success mb-3">
              <div class="card-header">
                <ng-content select=".header"></ng-content>
              </div>
              <div class="card-body">
                <ng-content select=".body"></ng-content>
              </div>
          </div>
  `
})
export class PanelComponent {

}

Let's view the results in our Chromium Web Browser:

NgIf:

import { Component } from '@angular/core';

@Component({
  selector: 'app-technologies',
  template: `
        <div class="row">
          <div class="col-6">
          <div *ngIf="technologies.length > 0; then technologiesList else noTechnologies;"></div>
          <ng-template #technologiesList>
          <h2 class="list-group-item list-group-item-danger">{{ title }}</h2></ng-template>
          <ng-template #noTechnologies><b>No technologies yet</b></ng-template>
          <ul class="list-group">
            <li *ngFor="let technology of technologies" class="list-group-item list-group-item-action">
            {{ technology }}
            </li>
          </ul>
        </div>
        <div class="col">
            <img class="w-100 p-3 rounded-circle" [src]="imageUrl" />
        </div>
      </div>
  `
})
export class TechnologiesComponent {
  title = 'List of Technologies';
  imageUrl = './assets/polymer1.jpg';

  technologies = ['Angular 5.0.0', 'Angular CLI 1.5.0', 'Angular Material 2.0.0', 'Ionic 3.0.0'];

}

Hidden Property:

<h2 [hidden]="technologies.length === 0" class="list-group-item list-group-item-danger">{{ title }}</h2>
<div [hidden]="technologies.length > 0">No technologies yet</div>

  technologies = ['Angular 5.0.0', 'Angular CLI 1.5.0', 'Angular Material 2.0.0', 'Ionic 3.0.0'];

Let's view the results in our Chromium Browser:

NgSwitch Directives Revisited:

import { Component } from '@angular/core';

@Component({
  selector: 'app-technologies',
  template: `
        <div class="row">
          <div class="col-6">
          <h2 class="list-group-item list-group-item-danger">{{ title }}</h2>
          <ul class="nav nav-pills">
              <li class="nav-item">
                <a class="nav-link" [class.active]="viewMode === 'list'"
                (click)="viewMode = 'list'">List View</a>
             </li>
             <li class="nav-item">
               <a class="nav-link" [class.active]="viewMode === 'card'"
               (click)="viewMode = 'card'">Card View</a>
            </li>
         </ul>
         <div [ngSwitch]="viewMode">
              <div *ngSwitchCase="'list'">
                <ul class="list-group">
                  <li *ngFor="let technology of technologies" class="list-group-item list-group-item-action">
                    {{ technology }}
                  </li>
                </ul>
              </div>
              <div *ngSwitchCase="'card'">
              <div class="card text-white bg-success mb-3">
                <div *ngFor="let technology of technologies" class="card-title">
                  {{ technology }}
                </div>
              </div>
              </div>
              <div *ngSwitchDefault>Default</div>
         </div>
        </div>
        <div class="col">
            <img class="w-100 p-3 rounded-circle" [src]="imageUrl" />
        </div>
      </div>
  `
})
export class TechnologiesComponent {
  title = 'List of Technologies';
  imageUrl = './assets/polymer1.jpg';
  viewMode = 'list';
  technologies = ['Angular 5.0.0', 'Angular CLI 1.5.0', 'Angular Material 2.0.0', 'Ionic 3.0.0'];

}

NgFor:

import { Component } from '@angular/core';

@Component({
  selector: 'app-technologies',
  template: `
        <div class="row">
          <div class="col-6">
          <h2>{{ title }}</h2>
          <ul>
                <li *ngFor="let technology of technologies; index as i;
                            odd as isOdd; even as isEven; first as isFirst; last as isLast;">
                ({{ i }}) - {{ technology.name }}
                <span *ngIf="isOdd">(ODD)</span>
                <span *ngIf="isEven">(EVEN)</span>
                <span *ngIf="isFirst">(FIRST)</span>
                <span *ngIf="isLast">(LAST)</span>
                </li>
          </ul>
        </div>
        <div class="col">
            <img class="w-100 p-3 rounded-circle" [src]="imageUrl" />
        </div>
      </div>
  `
})
export class TechnologiesComponent {
  title = 'List of Technologies';
  imageUrl = './assets/polymer1.jpg';
  technologies = [
                  { id: 1, name: 'Angular 5' },
                  { id: 2, name: 'Angular CLI 1.5' },
                  { id: 3, name: 'Angular Material 2' },
                  { id: 4, name: 'Angular Dart 4' }
                ];

}

NgFor && Change Detection:

import { Component } from '@angular/core';

@Component({
  selector: 'app-technologies',
  template: `
        <div class="row">
          <div class="col-6">
          <h2>{{ title }}</h2>
          <ul>
                <li *ngFor="let technology of technologies">
                {{ technology.name }}
                <button class="btn btn-warning btn-sm" (click)="onChange(technology)">Update</button>
                <button class="btn btn-danger btn-sm" (click)="onRemove(technology)">X</button>
                </li>
          </ul>
          <button class="btn btn-primary" (click)="onAdd()">Add</button>
        </div>
        <div class="col">
            <img class="w-100 p-3 rounded-circle" [src]="imageUrl" />
        </div>
      </div>
  `
})
export class TechnologiesComponent {
  title = 'List of Technologies';
  imageUrl = './assets/polymer1.jpg';
  technologies = [
                  { id: 1, name: 'Angular 5' },
                  { id: 2, name: 'Angular CLI 1.5' },
                  { id: 3, name: 'Angular Material 2' },
                  { id: 4, name: 'Angular Dart 4' }
                ];
  onAdd() {
    this.technologies.push({id: 5, name: 'Angular Universal' });
  }

  onRemove(technology) {
    const index = this.technologies.indexOf(technology);
    this.technologies.splice(index, 1);
  }

  onChange(technology) {
    technology.name = technology.name + ' UPDATED';
  }

}

NgFor & TrackBy:

import { Component } from '@angular/core';

@Component({
  selector: 'app-technologies',
  template: `
        <div class="row">
          <div class="col-6">
          <h2>{{ title }}</h2>
          <button class="btn btn-danger" (click)="loadTechnologies()">Load Technologies</button>
          <ul>
                <li *ngFor="let technology of technologies; trackBy: trackTechnology;">
                {{ technology.name }}
                </li>
          </ul>
        </div>
        <div class="col">
            <img class="w-100 p-3 rounded-circle" [src]="imageUrl" />
        </div>
      </div>
  `
})
export class TechnologiesComponent {
  title = 'List of Technologies';
  imageUrl = './assets/polymer1.jpg';
  technologies;

  loadTechnologies() {
    this.technologies = [
                    { id: 1, name: 'Angular 5' },
                    { id: 2, name: 'Angular CLI 1.5' },
                    { id: 3, name: 'Angular Material 2' },
                    { id: 4, name: 'Angular Dart 4' }
        ];
    }
  trackTechnology(index, technology) {
    return technology ? technology.id : undefined;
  }

}

The Leading Star in NgIf (desugared):

          <div *ngIf="technologies.length > 0; else noTechnologies;">
          <h2>{{ title }}</h2>
          </div>
          <ng-template #noTechnologies>
          <h2>No Technologies</h2>
          </ng-template>

          <ng-template [ngIf]="technologies.length > 0">
            <div><h2>{{ title }}</h2></div>
          </ng-template>
          <ng-template [ngIf]="!(technologies.length > 0)">
              <h2>No Technologies</h2>
          </ng-template>

results matching ""

    No results matching ""