Angular 2
パイプ
サーチ…
前書き
パイプ|
CharacterはAngular 2のパイプを適用するために使用されます。パイプはAngularJSのフィルタと非常によく似ています。これは、データを指定されたフォーマットに変換するのに役立ちます。
パラメーター
関数/パラメータ | 説明 |
---|---|
@Pipe({name、pure}) | パイプのメタデータ。パイプクラスの直前にある必要があります。 |
名前: 文字列 | テンプレートの中で何を使うか |
純粋な: ブール | デフォルト値はtrueです。これをfalseに設定すると、パイプの再評価がより頻繁に行われます |
transform(value、args []?) | テンプレート内の値を変換するために呼び出される関数 |
値: 任意 | 変換したい値 |
args: 任意の[] | あなたの変換に必要な引数があります。オプションのargsに?を付けます。演算子はそうですtransform(value、arg1、arg2?) |
備考
このトピックでは、Angular2アプリケーションでHTMLテンプレート内のデータを変換および書式設定するためのメカニズムであるAngular2 Pipesについて説明します。
チェインパイプ
パイプは連鎖することがあります。
<p>Today is {{ today | date:'fullDate' | uppercase}}.</p>
カスタムパイプ
my.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'myPipe'})
export class MyPipe implements PipeTransform {
transform(value:any, args?: any):string {
let transformedValue = value; // implement your transformation logic here
return transformedValue;
}
}
my.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'my-component',
template: `{{ value | myPipe }}`
})
export class MyComponent {
public value:any;
}
my.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { MyComponent } from './my.component';
import { MyPipe } from './my.pipe';
@NgModule({
imports: [
BrowserModule,
],
declarations: [
MyComponent,
MyPipe
],
})
export class MyModule { }
内蔵パイプ
Angular2にはいくつかのビルトインパイプが付属しています:
パイプ | 使用法 | 例 |
---|---|---|
DatePipe | date | {{ dateObj | date }} // output is 'Jun 15, 2015' |
UpperCasePipe | uppercase | {{ value | uppercase }} // output is 'SOMETEXT' |
LowerCasePipe | lowercase | {{ value | lowercase }} // output is 'sometext' |
CurrencyPipe | currency | {{ 31.00 | currency:'USD':true }} // output is '$31' |
PercentPipe | percent | {{ 0.03 | percent }} //output is %3 |
他にもあります。 ここでその文書を見てください。
例
hotel-reservation.component.ts
import { Component } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'hotel-reservation',
templateUrl: './hotel-reservation.template.html'
})
export class HotelReservationComponent {
public fName: string = 'Joe';
public lName: string = 'SCHMO';
public reservationMade: string = '2016-06-22T07:18-08:00'
public reservationFor: string = '2025-11-14';
public cost: number = 99.99;
}
hotel-reservation.template.html
<div>
<h1>Welcome back {{fName | uppercase}} {{lName | lowercase}}</h1>
<p>
On {reservationMade | date} at {reservationMade | date:'shortTime'} you
reserved room 205 for {reservationDate | date} for a total cost of
{cost | currency}.
</p>
</div>
出力
Welcome back JOE schmo
On Jun 26, 2016 at 7:18 you reserved room 205 for Nov 14, 2025 for a total cost of
$99.99.
JsonPipeによるデバッグ
JsonPipeは、任意の内部の状態をデバッグするために使用できます。
コード
@Component({
selector: 'json-example',
template: `<div>
<p>Without JSON pipe:</p>
<pre>{{object}}</pre>
<p>With JSON pipe:</p>
<pre>{{object | json}}</pre>
</div>`
})
export class JsonPipeExample {
object: Object = {foo: 'bar', baz: 'qux', nested: {xyz: 3, numbers: [1, 2, 3, 4, 5]}};
}
出力
Without JSON Pipe:
object
With JSON pipe:
{object:{foo: 'bar', baz: 'qux', nested: {xyz: 3, numbers: [1, 2, 3, 4, 5]}}
グローバルに使用可能なカスタムパイプ
アプリケーションのブートストラップ時に、PLATFORM_PIPESを拡張して、カスタムパイプをアプリケーション全体で使用可能にする。
import { bootstrap } from '@angular/platform-browser-dynamic';
import { provide, PLATFORM_PIPES } from '@angular/core';
import { AppComponent } from './app.component';
import { MyPipe } from './my.pipe'; // your custom pipe
bootstrap(AppComponent, [
provide(PLATFORM_PIPES, {
useValue: [
MyPipe
],
multi: true
})
]);
チュートリアルはこちら: https : //scotch.io/tutorials/create-a-globally-available-custom-pipe-in-angular-2
カスタムパイプの作成
app / pipes.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'truthy'})
export class Truthy implements PipeTransform {
transform(value: any, truthy: string, falsey: string): any {
if (typeof value === 'boolean'){return value ? truthy : falsey;}
else return value
}
}
app / my-component.component.ts
import { Truthy} from './pipes.pipe';
@Component({
selector: 'my-component',
template: `
<p>{{value | truthy:'enabled':'disabled' }}</p>
`,
pipes: [Truthy]
})
export class MyComponent{ }
非同期パイプによる非同期値のラップ解除
import { Component } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
@Component({
selector: 'async-stuff',
template: `
<h1>Hello, {{ name | async }}</h1>
Your Friends are:
<ul>
<li *ngFor="let friend of friends | async">
{{friend}}
</li>
</ul>
`
})
class AsyncStuffComponent {
name = Promise.resolve('Misko');
friends = Observable.of(['Igor']);
}
になる:
<h1>Hello, Misko</h1>
Your Friends are:
<ul>
<li>
Igor
</li>
</ul>
既存パイプの延長
import { Pipe, PipeTransform } from '@angular/core';
import { DatePipe } from '@angular/common'
@Pipe({name: 'ifDate'})
export class IfDate implements PipeTransform {
private datePipe: DatePipe = new DatePipe();
transform(value: any, pattern?:string) : any {
if (typeof value === 'number') {return value}
try {
return this.datePipe.transform(value, pattern)
} catch(err) {
return value
}
}
}
ステートフルパイプ
角度2は、ステートレスとステートフルの2種類のパイプを提供します。パイプはデフォルトではステートレスです。しかし、 pure
プロパティをfalse
設定することでステートフルパイプを実装できfalse
。パラメータセクションで分かるように、 name
を指定して、パイプが純粋かどうか、ステートフルかステートレスかを宣言することができます。データは、何も覚えていないステートレスなパイプ(純粋な関数)を通って流れますが、ステートフルパイプによってデータを管理して記憶することができます。ステートフルパイプの良い例は、Angular 2によって提供されるAsyncPipe
です。
重要
ほとんどのパイプはステートレスパイプのカテゴリに分類されることに注意してください。 Angularは変更検出器のステートレスパイプを最適化できるため、パフォーマンス上の理由から重要です。ステートフルパイプは慎重に使用してください。一般に、Angular 2のパイプの最適化は、Angular 1.xのフィルタよりも大きな性能向上をもたらします。角度1では、ダイジェストサイクルは、データがまったく変更されていなくても、常にすべてのフィルタを再実行する必要がありました。 Angular 2では、パイプの値が計算されると、入力が変更されない限り、変更検出器はこのパイプを再度実行しないことを認識します。
ステートフルパイプの実装
import {Pipe, PipeTransform, OnDestroy} from '@angular/core';
@Pipe({
name: 'countdown',
pure: false
})
export class CountdownPipe implements PipeTransform, OnDestroy {
private interval: any;
private remainingTime: number;
transform(value: number, interval: number = 1000): number {
if (!parseInt(value, 10)) {
return null;
}
if (typeof this.remainingTime !== 'number') {
this.remainingTime = parseInt(value, 10);
}
if (!this.interval) {
this.interval = setInterval(() => {
this.remainingTime--;
if (this.remainingTime <= 0) {
this.remainingTime = 0;
clearInterval(this.interval);
delete this.interval;
}
}, interval);
}
return this.remainingTime;
}
ngOnDestroy(): void {
if (this.interval) {
clearInterval(this.interval);
}
}
}
パイプを通常通り使用することができます:
{{ 1000 | countdown:50 }}
{{ 300 | countdown }}
パイプがOnDestroy
インターフェイスも実装することが重要ですので、パイプが破棄されるとクリーンアップできます。上記の例では、メモリリークを避けるために間隔をクリアする必要があります。
ダイナミックパイプ
ユースケースシナリオ:テーブルビューは、異なるパイプで変換する必要のある異なるデータ形式の異なる列で構成されています。
table.component.ts
... import { DYNAMIC_PIPES } from '../pipes/dynamic.pipe.ts'; @Component({ ... pipes: [DYNAMIC_PIPES] }) export class TableComponent { ... // pipes to be used for each column table.pipes = [ null, null, null, 'humanizeDate', 'statusFromBoolean' ], table.header = [ 'id', 'title', 'url', 'created', 'status' ], table.rows = [ [ 1, 'Home', 'home', '2016-08-27T17:48:32', true ], [ 2, 'About Us', 'about', '2016-08-28T08:42:09', true ], [ 4, 'Contact Us', 'contact', '2016-08-28T13:28:18', false ], ... ] ... }
dynamic.pipe.ts
import { Pipe, PipeTransform } from '@angular/core'; // Library used to humanize a date in this example import * as moment from 'moment'; @Pipe({name: 'dynamic'}) export class DynamicPipe implements PipeTransform { transform(value:string, modifier:string) { if (!modifier) return value; // Evaluate pipe string return eval('this.' + modifier + '(\'' + value + '\')') } // Returns 'enabled' or 'disabled' based on input value statusFromBoolean(value:string):string { switch (value) { case 'true': case '1': return 'enabled'; default: return 'disabled'; } } // Returns a human friendly time format e.g: '14 minutes ago', 'yesterday' humanizeDate(value:string):string { // Humanize if date difference is within a week from now else returns 'December 20, 2016' format if (moment().diff(moment(value), 'days') < 8) return moment(value).fromNow(); return moment(value).format('MMMM Do YYYY'); } } export const DYNAMIC_PIPES = [DynamicPipe];
table.component.html
<table> <thead> <td *ngFor="let head of data.header">{{ head }}</td> </thead> <tr *ngFor="let row of table.rows; let i = index"> <td *ngFor="let column of row">{{ column | dynamic:table.pipes[i] }}</td> </tr> </table>
結果
| ID | Page Title | Page URL | Created | Status | --------------------------------------------------------------------- | 1 | Home | home | 4 minutes ago | Enabled | | 2 | About Us | about | Yesterday | Enabled | | 4 | Contact Us | contact | Yesterday | Disabled | ---------------------------------------------------------------------
パイプのテスト
文字列を反転するパイプを指定すると
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'reverse' })
export class ReversePipe implements PipeTransform {
transform(value: string): string {
return value.split('').reverse().join('');
}
}
このようにspecファイルを設定してテストすることができます
import { TestBed, inject } from '@angular/core/testing';
import { ReversePipe } from './reverse.pipe';
describe('ReversePipe', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [ReversePipe],
});
});
it('should be created', inject([ReversePipe], (reversePipe: ReversePipe) => {
expect(reversePipe).toBeTruthy();
}));
it('should reverse a string', inject([ReversePipe], (reversePipe: ReversePipe) => {
expect(reversePipe.transform('abc')).toEqual('cba');
}));
});