How to custom Angular pipe
Pipes 是一個簡單的涵式,主要的功能是將我們要顯示的值/數據以另一種型式呈現,內建的 pipes 功能有大/小寫轉換、貨幣轉成本地格式、數字轉百分比、日期格式轉換,或是將值轉換成 JSON 格式,等等….
這些內建 pipes 最大的特點:
- 可以直接在 Template 中使用,無須在 Component 內撰寫轉換邏輯。
- 同樣的 pipe ,可以重複使用在不同的地方。
內建的 pipes,已經可以解決大部分的需求,但專案是多變的,客戶會提出怎樣的需求,我們通常無法左右,若轉換需求內建 Pipes 辦不到,且很多地方會用到,難道只能靠共用函式處理嗎?其實,我們可以使用更優雅的方式解決,以下我就來示範如何客製化 Pipe 元件。
目前有個情境是這樣的:將英哩轉公里。
建立新專案
app.component.html
,範本如下:1
2
3
4<label>英里(mile):</label>
<input (input)="onConvert($event.target.value)" />
<p></p>
公里(km):{{ distance }}app.component.ts
:1
2
3
4
5
6
7
8export class AppComponent {
distance = 0;
onConvert(value: string) {
this.distance = +value;
}
}呈現結果:
使用
Angular CLI
建立新的pipe
1
ng g pipe convert --skip-tests
g
– generatepipe
– 建立的類別為 pipeconvert
– 自訂 pipe 的名稱skip-tests
– 不需要測試檔Angular 會自動將 pipe 加入到根模組(
app.module.ts
)的declarations
陣列1
2
3
4
5
6
7
8
9
10
11@NgModule({
declarations: [
AppComponent,
ConvertPipe
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})檢視新增的
convert.pipe.ts
結構1
2
3
4
5
6
7
8
9@Pipe({
name: 'convert'
})
export class ConvertPipe implements PipeTransform {
transform(value: unknown, ...args: unknown[]): unknown {
return null;
}
}@Pipe
: 這是decorator
,將此 class 標記為 pipe。PipeTransform
:讓 class 實作此PipeTransform
介面,呼叫此介面的transform()
函式,執行轉換。transform()
:轉換函式,該函式會將綁定的值,作為第一個引數,也就是 Template 中的distance
,並回傳轉換後的值。在
transform()
內實現如何轉換:1
2
3transform(value: number, ...args: string[]): unknown {
return value * 1.06;
}我們將參數 value 的型別,由
unknown
改為number
。如同
@Component
的selector
一樣,在 Template 找到@Pipe
的name
,我們就可以使用客製化 pipe:1
公里(km):{{ distance | convert }}
結果:
如果需求改成可以將將英哩轉公里、碼、呎,那該如何判斷需轉成何種單位?這時會需要第二個參數(…args)
1
2
3transform(value: number, ...args: string[]) {
console.log(args);
}…args 是陣列型別,我們改成字串陣列。
如果 pipe 接受多個參數,需使用冒號(:)隔開1
公里(km):{{ distance | convert: "km":"yd" }}
輸入的引數會以陣列的形式呈現
第二個參數,我們使用字串即可,再搭配 switch 篩選單位換算
convert.pipe.ts
1
2
3
4
5
6
7
8
9
10
11
12transform(value: number, unit: string) {
switch (unit) {
case 'km':
return value * 1.60935;
case 'yd':
return value * 1760;
case 'ft':
return value * 5280;
default:
return value;
}
}app.component.html
1
2
3
4
5
6
7
8<label>英里(mile):</label>
<input (input)="onConvert($event.target.value)" />
<p></p>
公里(km):{{ distance | convert: "km" }}
<p></p>
碼(yd):{{ distance | convert: "yd" }}
<p></p>
英呎(ft):{{ distance | convert: "ft" }}結果:
以上就是客製化 pipe 的示範,
優點:
- 可以在不同地方共用同一個 pipe,不須再撰寫重複邏輯。
- 若是複雜的邏輯,pipe 可以將邏輯抽出來,簡化 component 內的程式碼,讓 component 更好維護。