@Pipe
| 対応: | Angular 14(2022) |
|---|
『Angular』の @Pipe は、カスタムパイプを定義するためのデコレーターです。パイプはテンプレート内で値を変換・整形するために使用され、@Pipe デコレーターを付けたクラスに transform() メソッドを実装することで、独自の変換ロジックを作成できます。
構文
// @Pipe デコレーターを付けることでクラスをカスタムパイプとして定義します
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
// テンプレートで使用するパイプ名を指定します
name: 'パイプ名',
// pure: true(デフォルト)の場合、入力値が変わらない限り再実行しません
pure: true,
})
export class カスタムパイプ名 implements PipeTransform {
// value: 変換前の値, ...args: テンプレートから渡す任意の追加引数
transform(value: any, ...args: any[]): any {
// 変換後の値を返します
return value;
}
}
@Pipe オプション一覧
| オプション | 型 | 概要 |
|---|---|---|
name | string | テンプレート内でパイプを呼び出す際の名前を指定します。必須プロパティです。 |
pure | boolean | true(デフォルト)の場合、入力値または参照が変化したときのみ transform() が再実行されます。false にすると変更検知のたびに毎回実行されるため、パフォーマンスに注意が必要です。 |
standalone | boolean | true にすると NgModule に登録せずに単独で使用できるスタンドアロンパイプになります。Angular 14 以降で利用可能です。 |
サンプルコード
文字列を指定した文字数で切り詰め、末尾に「…」を付加するカスタムパイプを定義し、テンプレートで使用する例です。
// truncate.pipe.ts
// 文字列を指定した最大文字数で切り詰めるカスタムパイプを定義します
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'truncate', // テンプレートでは {{ 値 | truncate:最大文字数 }} と記述します
})
export class TruncatePipe implements PipeTransform {
// value: 変換対象の文字列, limit: 最大文字数(デフォルト20文字)
transform(value: string, limit: number = 20): string {
// 値が空またはlimit以内の長さであればそのまま返します
if (!value || value.length <= limit) {
return value;
}
// limit文字で切り詰め、末尾に「…」を付加して返します
return value.substring(0, limit) + '…';
}
}
// article.component.ts
// TruncatePipe を使用してタイトルを切り詰めて表示するコンポーネントです
import { Component } from '@angular/core';
import { TruncatePipe } from './truncate.pipe';
@Component({
selector: 'app-article',
// | truncate:10 と記述することで最大10文字に切り詰めます
template: `
<h1>{{ title | truncate:10 }}</h1>
<p>{{ description | truncate:50 }}</p>
`,
// スタンドアロンコンポーネントの場合は imports に直接追加します
imports: [TruncatePipe],
standalone: true,
})
export class ArticleComponent {
title = 'Angularでカスタムパイプを作成する方法';
description = 'Angularのパイプ機能を使うと、テンプレート内で値を簡単に変換・整形できます。カスタムパイプを定義することで再利用性が高まります。';
}
// temperature.pipe.ts
// 摂氏(℃)を華氏(℉)へ変換するパイプと、逆変換を引数で切り替える例です
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'temperature',
standalone: true, // NgModule 不要のスタンドアロンパイプとして定義します
})
export class TemperaturePipe implements PipeTransform {
// value: 変換元の温度, unit: 変換先の単位('F' または 'C'、デフォルト 'F')
transform(value: number, unit: 'F' | 'C' = 'F'): string {
if (unit === 'F') {
// 摂氏 → 華氏の変換式: °F = °C × 9/5 + 32
const fahrenheit = value * 9 / 5 + 32;
return fahrenheit.toFixed(1) + ' °F';
} else {
// 華氏 → 摂氏の変換式: °C = (°F - 32) × 5/9
const celsius = (value - 32) * 5 / 9;
return celsius.toFixed(1) + ' °C';
}
}
}
// weather.component.ts
// TemperaturePipe をテンプレートで使用する例です
import { Component } from '@angular/core';
import { TemperaturePipe } from './temperature.pipe';
@Component({
selector: 'app-weather',
template: `
<p>東京の気温: {{ celsius | temperature }}</p>
<p>ニューヨークの気温: {{ fahrenheit | temperature:'C' }}</p>
`,
imports: [TemperaturePipe],
standalone: true,
})
export class WeatherComponent {
celsius = 25; // 摂氏25℃ → テンプレートで 77.0 °F と表示されます
fahrenheit = 86; // 華氏86℉ → テンプレートで 30.0 °C と表示されます
}
概要
@Pipe デコレーターは、テンプレート内でデータを変換するためのカスタムパイプを定義します。PipeTransform インターフェースを実装し、transform() メソッドに変換ロジックを記述するだけで、{{ 値 | パイプ名 }} の形式でテンプレートから呼び出せるようになります。
デフォルトでは pure: true として動作するため、入力値のプリミティブ値が変わらない限り transform() は再実行されません。オブジェクトや配列の内部変更を検知したい場合は pure: false を指定しますが、変更検知のたびに毎回実行されるためパフォーマンスへの影響に注意が必要です。
Angular 14 以降では standalone: true オプションを付けることで NgModule に登録せずに利用できます。スタンドアロンコンポーネントとの組み合わせについては スタンドアロンコンポーネント もあわせてご覧ください。また、テンプレート内でのデータバインディングの書き方については インターポレーション もご参照ください。
よくあるミス: pure パイプにオブジェクトの内部変更を検知させようとする
@Pipe({ pure: true })(デフォルト)のパイプは、入力値の参照が変わらない限り transform() を再実行しません。オブジェクトのプロパティだけを変えても参照は同じなので、パイプが再実行されず意図した表示にならないことがあります。
NG
// power-level.pipe.ts(pure パイプ)
import { Pipe, PipeTransform } from '@angular/core';
interface Fighter {
name: string;
power: number;
}
@Pipe({ name: 'powerLabel', standalone: true })
export class PowerLabelPipe implements PipeTransform {
transform(fighter: Fighter): string {
return fighter.name + ': ' + fighter.power;
}
}
// battle.component.ts
import { Component } from '@angular/core';
import { PowerLabelPipe } from './power-level.pipe';
@Component({
selector: 'app-battle',
template: `<p>{{ goku | powerLabel }}</p>`,
imports: [PowerLabelPipe],
standalone: true,
})
export class BattleComponent {
goku = { name: 'Son Goku', power: 9000 };
boost(): void {
// 同じオブジェクト参照のままプロパティを変更しても pure パイプは再実行されません
this.goku.power = 150000000;
}
}
OK
// battle.component.ts
import { Component } from '@angular/core';
import { PowerLabelPipe } from './power-level.pipe';
@Component({
selector: 'app-battle',
template: `<p>{{ goku | powerLabel }}</p>`,
imports: [PowerLabelPipe],
standalone: true,
})
export class BattleComponent {
goku = { name: 'Son Goku', power: 9000 };
boost(): void {
// スプレッド構文で新しいオブジェクト参照を作ると pure パイプが再実行されます
this.goku = { ...this.goku, power: 150000000 };
}
}
よくあるミス: @Pipe の name プロパティを省略する
@Pipe デコレーターの name プロパティは必須です。省略するとコンパイルエラーになります。また、name にはテンプレート内で実際に使う名前を正確に指定する必要があります。
NG
// energy.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
// name プロパティがないためコンパイルエラーになります
@Pipe({
standalone: true,
})
export class EnergyPipe implements PipeTransform {
transform(value: number): string {
return value >= 9000 ? '超サイヤ人レベル' : '通常レベル';
}
}
OK
// energy.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
// name に 'energy' を指定するとテンプレートで {{ value | energy }} と使えます
@Pipe({
name: 'energy',
standalone: true,
})
export class EnergyPipe implements PipeTransform {
transform(value: number): string {
return value >= 9000 ? '超サイヤ人レベル' : '通常レベル';
}
}
// power-display.component.ts
import { Component } from '@angular/core';
import { EnergyPipe } from './energy.pipe';
@Component({
selector: 'app-power-display',
// テンプレート内で | energy と記述して使います
template: `
<p>Vegeta の戦闘力: {{ vegetaPower | energy }}</p>
<p>Krillin の戦闘力: {{ krillinPower | energy }}</p>
`,
imports: [EnergyPipe],
standalone: true,
})
export class PowerDisplayComponent {
vegetaPower = 18000;
krillinPower = 1770;
}
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。