ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 08 구조 디렉티브(Structural Directive) 06
    앵귤러/03 템플릿&데이터 바인딩 2017. 9. 2. 13:06

    요약

    라이브 예제 / 예제 다운로드에서 이 가이드의 소스 코드를 다운로드 할 수 있습니다.

     

    다음은 src/app/ 폴더의 소스입니다.

    src/app/app.component.ts

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

     

    import { Hero, heroes } from './hero';

     

    @Component({

      selector: 'my-app',

      templateUrl: './app.component.html',

      styleUrls: [ './app.component.css' ]

    })

    export class AppComponent {

      heroes = heroes;

      hero = this.heroes[0];

     

      condition = false;

      logs: string[] = [];

      showSad = true;

      status = 'ready';

     

      trackById(index: number, hero: Hero): number { return hero.id; }

    }

     

    src/app/app.component.html

    <h1>Structural Directives</h1>

     

    <p>Conditional display of hero</p>

     

    <blockquote>

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

    </blockquote>

     

    <p>List of heroes</p>

     

    <ul>

      <li *ngFor="let hero of heroes">{{hero.name}}</li>

    </ul>

     

    <hr>

     

    <h2 id="ngIf">NgIf</h2>

     

    <p *ngIf="true">

      Expression is true and ngIf is true.

      This paragraph is in the DOM.

    </p>

    <p *ngIf="false">

      Expression is false and ngIf is false.

      This paragraph is not in the DOM.

    </p>

     

    <p [style.display]="'block'">

      Expression sets display to "block".

      This paragraph is visible.

    </p>

    <p [style.display]="'none'">

      Expression sets display to "none".

      This paragraph is hidden but still in the DOM.

    </p>

     

    <h4>NgIf with template</h4>

    <p>&lt;ng-template&gt; element</p>

    <ng-template [ngIf]="hero">

      <div>{{hero.name}}</div>

    </ng-template>

     

    <p>template attribute</p>

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

     

    <hr>

     

    <h2 id="ng-container">&lt;ng-container&gt;</h2>

     

    <h4>*ngIf with a &lt;ng-container&gt;</h4>

     

    <button (click)="hero = hero ? null : heroes[0]">Toggle hero</button>

     

    <p>

      I turned the corner

      <ng-container *ngIf="hero">

        and saw {{hero.name}}. I waved

      </ng-container>

      and continued on my way.

    </p>

    <p>

      I turned the corner

      <span *ngIf="hero">

        and saw {{hero.name}}. I waved

      </span>

      and continued on my way.

    </p>

     

    <p><i>&lt;select&gt; with &lt;span&gt;</i></p>

    <div>

      Pick your favorite hero

      (<label><input type="checkbox" checked (change)="showSad = !showSad">show sad</label>)

    </div>

    <select [(ngModel)]="hero">

      <span *ngFor="let h of heroes">

        <span *ngIf="showSad || h.emotion !== 'sad'">

          <option [ngValue]="h">{{h.name}} ({{h.emotion}})</option>

        </span>

      </span>

    </select>

     

    <p><i>&lt;select&gt; with &lt;ng-container&gt;</i></p>

    <div>

      Pick your favorite hero

      (<label><input type="checkbox" checked (change)="showSad = !showSad">show sad</label>)

    </div>

    <select [(ngModel)]="hero">

      <ng-container *ngFor="let h of heroes">

        <ng-container *ngIf="showSad || h.emotion !== 'sad'">

          <option [ngValue]="h">{{h.name}} ({{h.emotion}})</option>

        </ng-container>

      </ng-container>

    </select>

    <br><br>

     

    <hr>

     

    <h2 id="ngFor">NgFor</h2>

     

    <div class="box">

     

    <p class="code">&lt;div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd"&gt;</p>

    <div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd">

      ({{i}}) {{hero.name}}

    </div>

     

    <p class="code">&lt;div template="ngFor let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd"&gt;</p>

    <div template="ngFor let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd">

      ({{i}}) {{hero.name}}

    </div>

     

    <p class="code">&lt;template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById"&gt;</p>

    <ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById">

      <div [class.odd]="odd">({{i}}) {{hero.name}}</div>

    </ng-template>

     

    </div>

    <hr>

     

    <h2 id="ngSwitch">NgSwitch</h2>

     

    <div>Pick your favorite hero</div>

    <p>

      <label *ngFor="let h of heroes">

        <input type="radio" name="heroes" [(ngModel)]="hero" [value]="h">{{h.name}}

      </label>

      <label><input type="radio" name="heroes" (click)="hero = null">None of the above</label>

    </p>

     

    <h4>NgSwitch</h4>

     

    <div [ngSwitch]="hero?.emotion">

      <happy-hero    *ngSwitchCase="'happy'"    [hero]="hero"></happy-hero>

      <sad-hero      *ngSwitchCase="'sad'"      [hero]="hero"></sad-hero>

      <confused-hero *ngSwitchCase="'confused'" [hero]="hero"></confused-hero>

      <unknown-hero  *ngSwitchDefault           [hero]="hero"></unknown-hero>

    </div>

     

    <h4>NgSwitch with <i>template</i> attribute</h4>

    <div [ngSwitch]="hero?.emotion">

      <happy-hero    template="ngSwitchCase 'happy'"    [hero]="hero"></happy-hero>

      <sad-hero      template="ngSwitchCase 'sad'"      [hero]="hero"></sad-hero>

      <confused-hero template="ngSwitchCase 'confused'" [hero]="hero"></confused-hero>

      <unknown-hero  template="ngSwitchDefault"         [hero]="hero"></unknown-hero>

    </div>

     

    <h4>NgSwitch with &lt;ng-template&gt;</h4>

    <div [ngSwitch]="hero?.emotion">

      <ng-template [ngSwitchCase]="'happy'">

        <happy-hero [hero]="hero"></happy-hero>

      </ng-template>

      <ng-template [ngSwitchCase]="'sad'">

        <sad-hero [hero]="hero"></sad-hero>

      </ng-template>

      <ng-template [ngSwitchCase]="'confused'">

        <confused-hero [hero]="hero"></confused-hero>

      </ng-template >

      <ng-template ngSwitchDefault>

        <unknown-hero [hero]="hero"></unknown-hero>

      </ng-template>

    </div>

     

    <hr>

     

    <h2>&lt;template&gt;</h2>

    <p>Hip!</p>

    <ng-template>

      <p>Hip!</p>

    </ng-template>

    <p>Hooray!</p>

     

    <hr>

     

    <h2 id="myUnless">UnlessDirective</h2>

    <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 *myUnless="condition" class="unless a">

      (A) This paragraph is displayed because the condition is false.

    </p>

     

    <p *myUnless="!condition" class="unless b">

      (B) Although the condition is true,

      this paragraph is displayed because myUnless is set to false.

    </p>

     

    <h4>UnlessDirective with template</h4>

     

    <p *myUnless="condition">Show this sentence unless the condition is true.</p>

     

    <p template="myUnless condition" class="code unless">

      (A) &lt;p template="myUnless condition" class="code unless"&gt;

    </p>

     

    <ng-template [myUnless]="condition">

      <p class="code unless">

        (A) &lt;template [myUnless]="condition"&gt;

      </p>

    </ng-template>

     

    src/app/app.component.css

    button {

      min-width: 100px;

      font-size: 100%;

    }

     

    .box {

      border: 1px solid gray;

      max-width: 600px;

      padding: 4px;

    }

    .choices {

      font-style: italic;

    }

     

    code, .code {

      background-color: #eee;

      color: black;

      font-family: Courier, sans-serif;

      font-size: 85%;

    }

     

    div.code {

      width: 400px;

    }

     

    .heroic {

      font-size: 150%;

      font-weight: bold;

    }

     

    hr {

      margin: 40px 0

    }

     

    .odd {

      background-colorpalegoldenrod;

    }

     

    td, th {

      text-align: left;

      vertical-align: top;

    }

     

    p span { color: red; font-size: 70%; }

     

    .unless {

      border: 2px solid;

      padding: 6px;

    }

     

    p.unless {

      width: 500px;

    }

     

    button.a, span.a, .unless.a {

      color: red;

      border-color: gold;

      background-color: yellow;

      font-size: 100%;

    }

     

    button.b, span.b, .unless.b {

      color: black;

      border-color: green;

      background-color: lightgreen;

      font-size: 100%;

    }

     

    src/app/app.module.ts

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

    import { FormsModule }   from '@angular/forms';

    import { BrowserModule } from '@angular/platform-browser';

     

    import { AppComponent }         from './app.component';

    import { heroSwitchComponents } from './hero-switch.components';

    import { UnlessDirective }    from './unless.directive';

     

    @NgModule({

      imports: [ BrowserModule, FormsModule ],

      declarations: [

        AppComponent,

        heroSwitchComponents,

        UnlessDirective

      ],

      bootstrap: [ AppComponent ]

    })

    export class AppModule { }

     

    src/app/hero.ts

    export class Hero {

      id: number;

      name: string;

      emotion?: string;

    }

     

    export const heroes: Hero[] = [

      { id: 1, name: 'Mr. Nice',  emotion: 'happy'},

      { id: 2, name: 'Narco',     emotion: 'sad' },

      { id: 3, name: 'Windstorm', emotion: 'confused' },

      { id: 4, name: 'Magneta'}

    ];

     

    src/app/hero-switch.components.ts

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

    import { Hero } from './hero';

     

    @Component({

      selector: 'happy-hero',

      template: `Wow. You like {{hero.name}}. What a happy hero ... just like you.`

    })

    export class HappyHeroComponent {

      @Input() hero: Hero;

    }

     

    @Component({

      selector: 'sad-hero',

      template: `You like {{hero.name}}? Such a sad hero. Are you sad too?`

    })

    export class SadHeroComponent {

      @Input() hero: Hero;

    }

     

    @Component({

      selector: 'confused-hero',

      template: `Are you as confused as {{hero.name}}?`

    })

    export class ConfusedHeroComponent {

      @Input() hero: Hero;

    }

     

    @Component({

      selector: 'unknown-hero',

      template: `{{message}}`

    })

    export class UnknownHeroComponent {

      @Input() hero: Hero;

      get message() {

        return this.hero && this.hero.name ?

          `${this.hero.name} is strange and mysterious.` :

          'Are you feeling indecisive?';

      }

    }

     

    export const heroSwitchComponents =

      [ HappyHeroComponent, SadHeroComponent, ConfusedHeroComponent, UnknownHeroComponent ];

     

    src/app/unless.directive.ts

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

     

    /**

     * Add the template content to the DOM unless the condition is true.

     *

     * If the expression assigned to `myUnless` evaluates to a truthy value

     * then the templated elements are removed removed from the DOM,

     * the templated elements are (re)inserted into the DOM.

     *

     * <div *ngUnless="errorCount" class="success">

     *   Congrats! Everything is great!

     * </div>

     *

     * ### Syntax

     *

     * - `<div *myUnless="condition">...</div>`

     * - `<div template="myUnless condition">...</div>`

     * - `<template [myUnless]="condition"><div>...</div></template>`

     *

     */

    @Directive({ selector: '[myUnless]'})

    export class UnlessDirective {

      private hasView = false;

     

      constructor(

        private templateRef: TemplateRef<any>,

        private viewContainer: ViewContainerRef) { }

     

      @Input() set myUnless(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;

        }

      }

    }

     

    당신은 다음 내용을 학습하였습니다.

    l  구조 디렉티브는 HTML 레이아웃을 조작합니다.

    l  적합한 호스트 엘리먼트가 없을 때 <ng-container>를 그룹화 엘리먼트로 사용합니다.

    l  Angular 별표(*) 구문을 <ng-template>로 해석합니다.

    l  NgIf, NgFor NgSwitch 내장 디렉티브에 대한 작동 방식

    l  <ng-template>으로 확장되는 microsyntax에 대해서.

    l  사용자 지정 구조 디렉티브 인 UnlessDirective를 작성하였습니다.

    댓글

Designed by Tistory.