###### tags: `Angular` `指令` Angular == # 常用指令 | 指令| 用途 | | ------- | :------- | | ng -v | 檢視Angular版本號 | | ng update | 更新Angular版本 | | ng serve --open | 啟用serve | | ng generate component `組件名稱` | 建立`組件名稱`之組件 | | ng g c `組件名稱` | 建立`組件名稱`之組件 | | ng g c `資料夾名稱`/`組件名稱` | 在`資料夾名稱`下 建立`組件名稱`之組件 | | ng new `專案名稱` | 建立`專案名稱`之專案 | | ng n `專案名稱` | 建立`專案名稱`之專案 | | ng generate `專案名稱` | 建立`專案名稱`建立資料夾及模組 | | ng g `專案名稱`| 建立`專案名稱`建立資料夾及模組 | # 資料繫結 - 內嵌繫結 - ```TypeScript {{property}} ``` - 屬性繫結 - ```TypeScript [property]='statement' ``` - 事件繫結 - ```TypeScript (event)='someMethod($event)' ``` - 雙向繫結 - ```TypeScript [(ngModel)]='property' ``` ========================================== ## 內嵌繫結 ========================================== >app.component.ts ```TypeScript import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Will-demo01'; // 字串內嵌繫結 url = 'https://angular.cn/tutorial/toh-pt5'; // 網址內嵌繫結 imgUrl = 'https://placehold.it/150x150/000000/FFFFFF?text=TEST'; constructor() { setTimeout(() => { this.title = 'The will will web'; } , 2000); } // 動態倒數變更內嵌繫結 } ``` >app.component.html ```html <div style="text-align:center"> <h1> {{ title }} </h1> <h2><a target="_blank" href="{{ url }}">Angular blog</a></h2> <!-- 屬性繫結href --> <img src= "{{imgUrl}}" /> <!-- 屬性繫結變化imgSrc --> <router-outlet></router-outlet> ``` ========================================== ## 屬性繫結 ========================================== >app.component.ts ```TypeScript import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Will-demo01'; // 字串內嵌繫結 url = 'https://angular.cn/tutorial/toh-pt5'; // 網址內嵌繫結 imgUrl = 'https://placehold.it/150x150/000000/FFFFFF?text=TEST'; constructor() { setTimeout(() => { this.title = 'The will will web'; } , 2000); } // 動態倒數變更內嵌繫結 } ``` >app.component.html ```html <div style="text-align:center"> <h1> {{ title }} </h1> <h2><a target="_blank" [href]="url">Angular blog</a></h2> <!-- 屬性繫結href --> <img src='https://placehold.it/150x150/7777ff/FFFFFF?text=TEST' [title]='title'/> <!-- 屬性繫結變化title --> <img [src]='imgUrl' [title]='title' /> <!-- 屬性繫結變化imgSrc --> <img src='https://placehold.it/150x150/ff7777/FFFFFF?text=TEST' [title]='title' [attr.data-title]='title' /> <router-outlet></router-outlet> ``` > Attribute & Property 在翻譯上皆為**屬性**但意義上並不同, 處理方法也不同 | 英文名稱&emsp;&emsp; | 使用方法&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp; | | ---------------------------------------------------------- | :----------------------------------------------------------- | | Property | [title]='pome' -> [title]='title' | Attribute | [attr.data-title]='title' - 注意事項 - =後的title皆為.ts檔內已宣告的值 - img 這個 DOM物件已存在 Title這個 Property屬性故可直接進行變化 - F12->properties->HTMLImageElement - 檢視DOM物件 檢視所有imgTag property屬性 - ``data-title``這個屬性並非原先已存在 而是我們後來自行定義的 - 故須在``data-title``前添加``arrt.`` -> [attr.data-title]='title' ========================================== ## 事件連結 ========================================== >app.component.ts ```TypeScript import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Will-demo01'; // 字串內嵌繫結 url = 'https://angular.cn/tutorial/toh-pt5'; // 網址內嵌繫結 imgUrl = 'https://placehold.it/150x150/000000/FFFFFF?text=TEST'; constructor() { } changeColor() { this.imgUrl = 'https://placehold.it/150x150/FFcccc/000000?text=TEST'; } // 建立事件繫結以改變已宣告之物件值 changeBlue() { this.imgUrl = 'https://placehold.it/150x150/CCCCFF/000000?text=TEST'; } } ``` >app.component.html ```html <h1> {{ title }} </h1> <h2><a target="_blank" [href]="url">Angular blog</a></h2> <img src='https://placehold.it/150x150/7777ff/FFFFFF?text=TEST' [title]='title'/> <img [src]='imgUrl' [title]='title' /> <!-- 建立建立事件繫結有兩種寫法 --> <!-- 1 --> <img on-click = "changeColor()" src='https://placehold.it/150x150/ff7777/FFFFFF?text=CCB' [title]='title' [attr.data-title]='title' /> <!-- 2 --> <img (click) = "changeBlue()" src='https://placehold.it/150x150/ff7777/FFFFFF?text=CCBlue' [title]='title' [attr.data-title]='title' /> <!-- 寶哥建議第二種的寫法 --> <router-outlet></router-outlet> ``` ### 事件繫結應用 > 事件``(click)``方法``changeBlue()`` 可為空值,預設可不給預設 > 也可傳入$event 並以console.log($event)回傳事件詳細資訊 > 藉由console.log($event)顯示此物件可配合的行為 如shift+click alt+click等變化事件 > 小心大小寫 >> 小心大小寫 >>> 小心大小寫 >app.component.ts ```TypeScript import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Will-demo01'; // 字串內嵌繫結 url = 'https://angular.cn/tutorial/toh-pt5'; // 網址內嵌繫結 // 動態倒數變更內嵌繫結 imgUrl = 'https://placehold.it/100x100/000000/FFFFFF?text=TEST'; constructor() { setTimeout(() => { this.title = 'The will will web'; } , 2000); } // 建立事件繫結以改變已宣告之物件值 changeBlue($event) { if ($event.altKey) { this.imgUrl = 'https://placehold.it/100x100/CCCCFF/000000?text=TEST'; } else { this.imgUrl = 'https://placehold.it/100x100/ffCCFF/000000?text=TEST'; } } } import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Will-demo01'; // 字串內嵌繫結 url = 'https://angular.cn/tutorial/toh-pt5'; // 網址內嵌繫結 // 動態倒數變更內嵌繫結 imgUrl = 'https://placehold.it/100x100/000000/FFFFFF?text=TEST'; constructor() { setTimeout(() => { this.title = 'The will will web'; } , 2000); } // 建立事件繫結以改變已宣告之物件值 changeBlue($event) { if ($event.altKey) { this.imgUrl = 'https://placehold.it/100x100/CCCCFF/000000?text=TEST'; } else { this.imgUrl = 'https://placehold.it/100x100/ffCCFF/000000?text=TEST'; } } } ``` >app.component.html ```html <!--The content below is only a placeholder and can be replaced.--> <div style="text-align:center"> <img (click) = "changeBlue($event)" src='https://placehold.it/350x100/ff7777/FFFFFF?text=alt+click' [title]='title' [attr.data-title]='title' /> <!-- !!!!!!!!小心大小寫!!!!!!!! --> <router-outlet></router-outlet> ``` >app.component.ts ```TypeScript import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Will-demo01'; // 字串內嵌繫結 url = 'https://angular.cn/tutorial/toh-pt5'; // 網址內嵌繫結 // 動態倒數變更內嵌繫結 imgUrl = 'https://placehold.it/100x100/000000/FFFFFF?text=TEST'; constructor() { setTimeout(() => { this.title = 'The will will web'; } , 2000); } // 回傳值非$even時 其型別要同時進行宣告 changeTitle(altKey: boolean) { if (altKey) { this.title = 'alt'; } else { this.title = 'no-alt'; } } } ``` >app.component.html ```html <!--The content below is only a placeholder and can be replaced.--> <h2><a target="_blank" [href]="url">Angular blog</a></h2> <!-- 屬性繫結變化title --> <img [src]='imgUrl' [title]='title' /> <!-- 屬性繫結變化imgSrc --> <img (click) = "changeTitle($event.altKey)" src='https://placehold.it/350x100/ff7777/FFFFFF?text=alt+click' [title]='title' [attr.data-title]='title' /> <!-- 相較於上一種寫法 指定變數為$event.altKey彈性校低但程式碼也較為簡潔 --> <router-outlet></router-outlet> ``` #### 延伸應用 ##### 保哥作業 ```TypeScript import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app'; url = 'http://blog.miniasp.com/'; imgurl = '/assets/images/logo.png'; // wordcont = 0; // 1.宣告一個變數 constructor() { } changeTitle(altKey: boolean) { if (altKey) { this.title = 'The Will Will Web'; } } } ``` ```html <div id="searchbox"> <!-- 於dom物件中註冊事件 與 事件方法 ex:keyup keyup.escape --> <input type="text" (keyup)="wordcount=$event.target.value.length" (keyup.escape)="wordcount=0;$event.target.value= ' ' ; " placeholder="請輸入搜尋關鍵字" accesskey="s"> <input type="button" value="搜尋" id="searchbutton"> <br>目前字數: {{ wordcount }} <!-- 2.與html內嵌繫結變數 --> </div> ``` > 寫法二 <!-- 將上述方法與html 分離寫在ts檔內 --> ```TypeScript import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app'; url = 'http://blog.miniasp.com/'; imgurl = '/assets/images/logo.png'; wordcont = 0; constructor() { } changeTitle(altKey: boolean) { if (altKey) { this.title = 'The Will Will Web'; } } // 1.宣告一個方法名稱 定義變數型別 keywordChanges(keyword: string) { this.wordcont = keyword.length; } keywordReset(input: HTMLInputElement) { input.value = ' '; this.wordcont = 0; } } ``` ```html <div id="searchbox"> <!-- 2.於事件註冊方法名稱 其變數設為$event應用事件 --> <!-- $event.target指向Dom物件應用 並指向value 則可搜尋使用者輸入值 --> <input type="text" (keyup)="keywordChanges($event.target.value)" (keyup.escape)="keywordReset($event.target)" placeholder="請輸入搜尋關鍵字" accesskey="s"> <input type="button" value="搜尋" id="searchbutton"> <br> 目前字數: {{ wordcont }} </div> ``` # 雙向繫結 >app.component.html ```html <div id="searchbox"> <!-- 1.額外新增input標籤的組件,刪除(keyup)="keywordChanges($event.target.value)" --> <input type="text" [(ngModel)]="keyword" (keyup.escape)="keywordReset($event.target)" placeholder="請輸入搜尋關鍵字" accesskey="s"> <input type="button" value="搜尋" id="searchbutton"> <br>關鍵字:{{ keyword }} <br>目前字數: {{ keyword.length }} <!-- 6.改為 keyword.length 原先宣告變數已不需要存在 --> </div> ``` >app.module.ts ```TypeScript // 預設 import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; // 2.額外新增 import { FormsModule } from '@angular/forms'; // 預設 import { AppComponent } from './app.component'; // 但凡上方額外新增 下方imports要連動 @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, FormsModule // 3.額外新增 ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } ``` >app.component.ts ```TypeScript import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app'; url = 'http://blog.miniasp.com/'; imgurl = '/assets/images/logo.png'; // 4. keyword = ''; constructor() { } changeTitle(altKey: boolean) { if (altKey) { this.title = 'The Will Will Web'; } } // 5. keywordReset() { this.keyword = ''; } } ``` # 範本參考變數 ( Template reference variables ) - 在範本中可任意於HTML標籤套用 ``#範本參考變數變數名稱`` - 該``#範本參考變數變數名稱``只能使用於所在該元件範本中 - 該``#範本參考變數變數名稱``將會儲存該標籤的DOM物件 - 可透過事件繫結將任意DOM物件中任意屬性傳回元件類別中(component class) ## 語法 - ``#範本參考變數變數名稱`` - ref-``範本參考變數變數名稱`` ## 指令介紹 (Directies) - 元件型指令 (Commpoent Directie) - 預設`元件`就是一個含有樣板的指令 ```html <app-root></app-root> ``` - 屬性型指令 - 修改外觀或行為 >以`a-`呼喚程式結構片段 ```html <h3 [ngStyle]="{style: expression}"> 學習心得與技術分享 {{counter}} </h3> ``` ## ngStyle ### 方法一 ```html <h3 [ngStyle]="{'font-size': (18+counter)+'px'}"> 學習心得與技術分享 {{counter}} </h3> <h3 [ngStyle]="{'font-size': (18+counter)+'px','color': 'red'}"> 記載著 Will 在網路世界的學習心得與技術分享{{counter}}</h3> <!-- 添加多種style,**英式逗號分隔** --> ``` ```TypeScript import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-header', templateUrl: './header.component.html', styleUrls: ['./header.component.css'] }) export class HeaderComponent implements OnInit { title = 'app'; url = 'http://blog.miniasp.com/'; imgurl = '/assets/images/logo.png'; counter = 0; constructor() { } changeTitle(altKey: boolean) { if (altKey) { this.title = 'The Will Will Web'; } this.counter++; } ngOnInit() { } } ``` ### 方法二 ```TypeScript import { Component, OnInit } from "@angular/core"; @Component({ selector: "app-header", templateUrl: "./header.component.html", styleUrls: ["./header.component.css"] }) export class HeaderComponent implements OnInit { title = "app"; url = "http://blog.miniasp.com/"; imgurl = "/assets/images/logo.png"; counter = 0; constructor() {} getStyle() { return { 'font-size': 18 + this.counter + 'px', color: 'red' }; } // 建立一個方法 回傳物件值 // 記得修正參數前須添加"this." changeTitle(altKey: boolean) { if (altKey) { this.title = 'The Will Will Web'; } this.counter++; } ngOnInit() {} } ``` ```html <h3 [ngStyle]="getStyle()"> 記載著 Will 在網路世界的學習心得與技術分享{{counter}}</h3> <!-- 導入方法 --> ``` ### 方法三 ```TypeScript import { Component, OnInit } from "@angular/core"; @Component({ selector: "app-header", templateUrl: "./header.component.html", styleUrls: ["./header.component.css"] }) export class HeaderComponent implements OnInit { title = "app"; url = "http://blog.miniasp.com/"; imgurl = "/assets/images/logo.png"; counter = 0; constructor() {} changeTitle(altKey: boolean) { if (altKey) { this.title = 'The Will Will Web'; } this.counter++; } ngOnInit() {} } ``` ```html <h3 [style.font-size]="(18+counter)+'px'"> 心得與技術分享{{counter}}</h3> <!-- 使用 [style.OOOO]=" (數值 + 數值運算)+'字串 如單位或英文'" --> <h3 [style.font-size]="( 18 + 2*counter )+'px'" > 心得與技術分享{{counter}}</h3> <h3 [style.font-size]="(18+counter)+'px'" [style.color]="'yellow'" >心得與技術分享{{counter}}</h3> <!-- 同時設定兩種style --> <h3 [style.color]="'#222222'" > 心得與技術分享{{counter}}</h3> <!-- 16進魏色碼也視為字串 --> ``` # ngClass ```TypeScript import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-header', templateUrl: './header.component.html', styleUrls: ['./header.component.css'] }) export class HeaderComponent implements OnInit { title = 'app'; url = 'http://blog.miniasp.com/'; imgurl = '/assets/images/logo.png'; counter = 0; constructor() {} changeTitle(altKey: boolean) { if (altKey) { this.title = 'The Will Will Web'; } this.counter++; } ngOnInit() {} } ``` ## 寫法一 ```html <h3 [ngClass]="{'hightlight': counter % 2 == 0 }" > 心得與技術分享{{counter}}</h3> <!-- 添加Class指定屬性 --> <!-- counter % 2 == 0 =>導入counter值 除以2 取餘數 若等於0為true 若不等於0 則為false =>雙數為成立 單數不成立 --> <!-- 詳情見 0-Markdone/ 運算子.md --> ``` ## 寫法二 ```html <h3 [class.hightlight]=" counter % 2 == 0" > 心得與技術分享{{counter}}</h3> <!-- [class.OOOclass名稱] = " 布林值(判斷式 true & false) " --> ``` - 結構型指令 - 新增 刪除 DOM 元素 來改變 DOM 結構 # NgIf ``` HTML <div class="pull-left" *ngIf="expression"> <!-- expression => 布林值 => 判斷式斷式 true & false --> <!-- true 顯示結構 false 刪除結構 --> ``` # NgFor ```html <article class="post" id="post0" *ngFor="let item of list"> </article> <!-- 對應資料結構導入資料 以item為傳喚值 --> <article class="post" id="post0" *ngFor="let item of data"> <header class="post-header"> <h2 class="post-title"> <a [href]="item.href">{{item.title}}</a> </h2> <div class="post-info clearfix"> <span class="post-date"> <i class="glyphicon glyphicon-calendar"></i>{{item.date}}</span> <span class="post-author"> <i class="glyphicon glyphicon-user"></i> <a href="http://blog.miniasp.com/author/will.aspx">{{item.author}}</a> </span> <span class="post-category"> <i class="glyphicon glyphicon-folder-close"></i> <a [href]="item['category-link']">{{item.category}}</a> <!-- 注意包含-的文字不可 item.category-link --> <!-- 不符合js的識別元 => item ['category-link'] => 以此傳喚item物件下的值 --> </span> </div> </header> <section class="post-body text" [innerHTML]="item.summary"> </section> </article> ``` # NgSwitch ``` html <div [ngSwitch]="conditionExpression"> <div *ngSwitchCase="expression">output</div> <div *ngSwitchDefault>output2</div> </div> <!-- conditionExpression =>判斷條件式 --> <!-- expression => 布林值 => 判斷式斷式 true & false --> ``` ```html <div id="social-icons" class="pull-right social-icon"> <ng-container [ngSwitch]="counter % 2 == 0"> <ng-container *ngSwitchCase="0"> <a href="https://www.facebook.com/will.fans" title="Will 保哥的技術交流中心" target="_blank"> <img src="/assets/images/facebook.png" /> </a> </ng-container> <ng-container *ngSwitchCase="1" > <a href="http://www.plurk.com/willh" title="★★★ Will 保哥的噗浪 ★★★" target="_blank"> <img src="/assets/images/plurk.png" /> </a> </ng-container> <ng-container *ngSwitchDefault>N/A </ng-container> </ng-container> </div> <!-- 可以 ng-container 取代預設div避免變動影響結構 --> ```