###### 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 在翻譯上皆為**屬性**但意義上並不同,
處理方法也不同
| 英文名稱   | 使用方法                  |
| ---------------------------------------------------------- | :----------------------------------------------------------- |
| 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避免變動影響結構 -->
```