Property Binding
| 対応: | Angular 14(2022) |
|---|
『Angular』のプロパティバインディング(Property Binding)は、コンポーネントクラスのプロパティや式の結果を、HTMLテンプレートの要素プロパティに動的に反映させる構文です。[プロパティ名]="式" の角括弧記法を使い、コンポーネント側の値が変わると『Angular』が自動的にDOMプロパティを更新します。
基本的な使い方
| 記法 | 説明 |
|---|---|
[プロパティ名]="値" | コンポーネントのプロパティ値をDOM要素のプロパティにバインドします。 |
[プロパティ名]="式" | 式を評価した結果をDOM要素のプロパティにバインドします。 |
[attr.属性名]="値" | DOMプロパティではなくHTML属性にバインドします(aria-*・colspan など)。 |
[class.クラス名]="真偽値" | 真偽値に応じてCSSクラスを付け外しします。 |
[style.スタイル名]="値" | インラインスタイルの値を動的に設定します。 |
基本的なプロパティバインディング
// app.component.ts
// [プロパティ名]="式" の形でDOMプロパティに値をバインドします
import { Component } from '@angular/core';
@Component({
standalone: true,
selector: 'app-root',
// ---- HTMLテンプレート部分 ----
// [src]="imageUrl" → img要素の src プロパティにコンポーネントの imageUrl をバインドします
// [alt]="imageAlt" → img要素の alt プロパティにコンポーネントの imageAlt をバインドします
// [disabled]="isDisabled" → button要素の disabled プロパティを真偽値でバインドします
// [value]="inputValue" → input要素の value プロパティに初期値をバインドします
template: `
<img [src]="imageUrl" [alt]="imageAlt" />
<button [disabled]="isDisabled">送信</button>
<input type="text" [value]="inputValue" />
`,
})
export class AppComponent {
// 表示する画像のURLです
imageUrl: string = 'https://example.com/photo.jpg';
// 画像の代替テキストです
imageAlt: string = 'サンプル画像';
// true のときボタンが無効化されます
isDisabled: boolean = true;
// テキスト入力の初期値です
inputValue: string = 'はじめの値';
}
式の評価結果をバインドする
// app.component.ts
// [プロパティ名]="式" の右辺には任意のTypeScript式を書けます
// 三項演算子・算術演算・メソッド呼び出しなどが使えます
import { Component } from '@angular/core';
@Component({
standalone: true,
selector: 'app-root',
// ---- HTMLテンプレート部分 ----
// [title]="getLabel()" → title属性(ツールチップ)にメソッドの戻り値をバインドします
// [href]="baseUrl + '/detail/' + productId" → 文字列を結合してURLを動的に生成します
// [tabIndex]="isActive ? 0 : -1" → 三項演算子でタブ順序を切り替えます
template: `
<span [title]="getLabel()">マウスを当ててください</span>
<a [href]="baseUrl + '/detail/' + productId">商品詳細へ</a>
<div [tabIndex]="isActive ? 0 : -1">コンテンツ</div>
`,
})
export class AppComponent {
// ベースURLです(環境によって切り替えることもできます)
baseUrl: string = 'https://example.com';
// 商品IDです(URLに組み込んで詳細ページへのリンクを生成します)
productId: number = 42;
// フォーカス可能かどうかを表す状態です
isActive: boolean = true;
// ツールチップ用のラベル文字列を返します
getLabel(): string {
return 'ID: ' + this.productId + ' の詳細を表示します';
}
}
attr. を使ったHTML属性バインディング
// app.component.ts
// DOMプロパティとして存在しないHTML属性(aria-* や colspan など)は
// [attr.属性名] の形で属性バインディングを使います
import { Component } from '@angular/core';
@Component({
standalone: true,
selector: 'app-root',
// ---- HTMLテンプレート部分 ----
// [attr.aria-label]="ariaLabel" → aria-label 属性を動的に設定します
// [attr.aria-expanded]="isOpen" → aria-expanded 属性を動的に設定します
// [attr.colspan]="colSpan" → th/td の colspan 属性を動的に設定します
template: `
<button [attr.aria-label]="ariaLabel" [attr.aria-expanded]="isOpen">
メニュー
</button>
<table>
<tr>
<th [attr.colspan]="colSpan">見出し</th>
</tr>
</table>
`,
})
export class AppComponent {
// ボタンのアクセシビリティラベルです
ariaLabel: string = 'ナビゲーションメニューを開く';
// メニューが展開されているかどうかです(aria-expanded に反映します)
isOpen: boolean = false;
// テーブルの見出し列が結合する列数です
colSpan: number = 3;
}
class. を使ったCSSクラスバインディング
// app.component.ts
// [class.クラス名]="真偽値" の形で、条件に応じてCSSクラスを付け外しできます
// 複数クラスをまとめて制御したい場合は [ngClass] ディレクティブも使えます
import { Component } from '@angular/core';
@Component({
standalone: true,
selector: 'app-root',
// ---- HTMLテンプレート部分 ----
// [class.active]="isActive" → isActive が true のとき active クラスを付与します
// [class.error]="hasError" → hasError が true のとき error クラスを付与します
// [class.highlight]="isHighlight" → isHighlight が true のとき highlight クラスを付与します
template: `
<div [class.active]="isActive" [class.error]="hasError">
ステータス表示エリア
</div>
<p [class.highlight]="isHighlight">
強調テキスト
</p>
`,
styles: [`
.active { border: 2px solid green; }
.error { color: red; }
.highlight { background-color: yellow; }
`],
})
export class AppComponent {
// アクティブ状態です(true のとき active クラスが付与されます)
isActive: boolean = true;
// エラー状態です(true のとき error クラスが付与されます)
hasError: boolean = false;
// 強調表示状態です(true のとき highlight クラスが付与されます)
isHighlight: boolean = true;
}
style. を使ったインラインスタイルバインディング
// app.component.ts
// [style.スタイルプロパティ]="値" の形で、インラインスタイルを動的に設定できます
// 単位が必要な場合は [style.width.px]="数値" のように単位をドットの後に指定します
import { Component } from '@angular/core';
@Component({
standalone: true,
selector: 'app-root',
// ---- HTMLテンプレート部分 ----
// [style.color]="textColor" → テキストの色を動的に変更します
// [style.font-size.px]="fontSize" → フォントサイズをピクセル単位で設定します
// [style.width.%]="progressValue" → 幅をパーセント単位で設定します(プログレスバーなど)
// [style.opacity]="opacity" → 透明度(0〜1)を設定します
template: `
<p [style.color]="textColor" [style.font-size.px]="fontSize">
スタイル変更サンプル
</p>
<div style="background:#ddd; width:200px; height:20px;">
<div [style.width.%]="progressValue" style="background:steelblue; height:100%;"></div>
</div>
<img src="sample.jpg" [style.opacity]="opacity" alt="サンプル" />
`,
})
export class AppComponent {
// テキストの色です(CSSカラー値で指定します)
textColor: string = 'steelblue';
// テキストのフォントサイズです(ピクセル単位)
fontSize: number = 18;
// プログレスバーの進捗率です(0〜100 のパーセント値)
progressValue: number = 65;
// 画像の透明度です(0: 完全透明、1: 完全不透明)
opacity: number = 0.8;
}
補間との使い分け
| 記法 | 適した用途 | 例 |
|---|---|---|
{{ 値 }} | テキストコンテンツとして表示するとき。 | <p>{{ name }}</p> |
[プロパティ]="値" | DOM要素のプロパティに値をセットするとき。 | <img [src]="url" /> |
[プロパティ]="値" | 真偽値を扱うプロパティ(disabled など)。 | <button [disabled]="flag"> |
NG
// app.component.ts
// src="{{ imageUrl }}" は文字列として属性に入るためセキュリティ警告が出る場合があります
// disabled="{{ isDisabled }}" は "false" という文字列になり、常に無効化されます
import { Component } from '@angular/core';
@Component({
standalone: true,
selector: 'app-root',
template: `
<img src="{{ imageUrl }}" alt="{{ imageAlt }}" />
<button disabled="{{ isDisabled }}">OK</button>
`,
})
export class AppComponent {
imageUrl: string = 'https://example.com/photo.jpg';
imageAlt: string = 'サンプル画像';
isDisabled: boolean = false;
}
OK
// app.component.ts
// [src]="imageUrl" はDOMのプロパティに直接バインドされます
// [disabled]="isDisabled" は真偽値としてDOMに渡されます
import { Component } from '@angular/core';
@Component({
standalone: true,
selector: 'app-root',
template: `
<!-- プロパティバインディング -->
<img [src]="imageUrl" [alt]="imageAlt" />
<button [disabled]="isDisabled">OK</button>
<!-- テキスト表示には補間を使います -->
<p>画像URL: {{ imageUrl }}</p>
`,
})
export class AppComponent {
// バインドする画像のURLです
imageUrl: string = 'https://example.com/photo.jpg';
// 画像の代替テキストです
imageAlt: string = 'サンプル画像';
// ボタンの無効状態です(false のときボタンは押せます)
isDisabled: boolean = false;
}
概要
『Angular』のプロパティバインディング([プロパティ名]="式")は、コンポーネントのデータをHTMLテンプレートの要素プロパティに動的に反映させるための構文です。src・disabled・value などのDOMプロパティだけでなく、[attr.*] によるHTML属性・[class.*] によるCSSクラス・[style.*] によるインラインスタイルもまとめて扱えます。
テキストコンテンツの表示には補間({{ }})、要素のプロパティに値をセットする場合はプロパティバインディング([])と使い分けるのが基本です。特に disabled のような真偽値プロパティや src のような安全性が重要なプロパティには、補間ではなくプロパティバインディングを使う方法が適しています。
プロパティバインディングはデータバインディングの中核となる構文です。関連するバインディングについては データバインディング や 補間(Interpolation) もあわせてご覧ください。
よくあるミス: 補間で disabled を設定して常に無効になる
disabled="{{ isDisabled }}" のように補間を使うと、isDisabled の値が false であっても文字列 "false" が属性にセットされます。HTML の disabled 属性は値に関係なく存在するだけで無効化されるため、ボタンが常に押せない状態になります。真偽値プロパティにはプロパティバインディングを使います。
NG
// battle.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-battle',
// disabled="{{ isDisabled }}" は "false" という文字列になるため常に無効になります
template: `
<button disabled="{{ isDisabled }}">攻撃する</button>
`,
standalone: true,
})
export class BattleComponent {
isDisabled: boolean = false; // false を渡したいが、"false" 文字列になってしまいます
}
OK
// battle.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-battle',
// [disabled]="isDisabled" で真偽値がそのまま DOM に渡されます
template: `
<button [disabled]="isDisabled">攻撃する</button>
`,
standalone: true,
})
export class BattleComponent {
isDisabled: boolean = false; // false のときボタンは押せます
}
よくあるミス: DOM プロパティと HTML 属性を混同して [attr.*] と [] を使い分けられない
[colspan]="n" のように書いても動作しません。colspan は DOM プロパティとして存在しないため、[attr.colspan]="n" の形で属性バインディングを使う必要があります。一方、src や disabled は DOM プロパティとして存在するため [src] や [disabled] と書きます。
NG
// team.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-team',
// colspan は DOM プロパティとして存在しないため [colspan] は動作しません
template: `
<table>
<tr><th [colspan]="colSpan">Z戦士チーム</th></tr>
<tr><td>Son Goku</td><td>Vegeta</td></tr>
</table>
`,
standalone: true,
})
export class TeamComponent {
colSpan: number = 2;
}
OK
// team.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-team',
// DOM プロパティが存在しない属性は [attr.属性名] で指定します
template: `
<table>
<tr><th [attr.colspan]="colSpan">Z戦士チーム</th></tr>
<tr><td>Son Goku</td><td>Vegeta</td></tr>
</table>
`,
standalone: true,
})
export class TeamComponent {
colSpan: number = 2;
}
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。