詳細ガイド
テンプレート構文

プロパティバインディングのベストプラクティス

いくつかのガイドラインに従うことで、バグを減らし、コードを可読性高く保つことができるようにプロパティバインディングを使用できます。

サイドエフェクトを避ける

テンプレート式の評価は、目に見える副作用があってはなりません。 テンプレート式の構文を使用して、副作用を避けるようにしてください。 一般的に、正しい構文により、プロパティバインディング式で何か他のものへの値の割り当ては不可能になります。 また、インクリメントとデクリメント演算子も使用できません。

サイドエフェクトを生成する例

バインドしているものとは異なるものの値を変更する式があった場合、その値の変更は副作用になります。 Angularは、変更された値を表示するかしない場合があります。 Angularが変更を検出すると、エラーが発生します。

ベストプラクティスとして、値を返すプロパティとメソッドのみを使用してください。

適切な型を返す

テンプレート式は、ターゲットプロパティが期待する型の値を生成する必要があります。 たとえば、次のようなものを返します。

  • string:ターゲットプロパティが文字列を期待する場合
  • number:数値を期待する場合
  • object:オブジェクトを期待する場合

文字列を渡す

次の例では、ItemDetailComponentchildItemプロパティは文字列を期待しています。

src/app/app.component.html

      
<div>
<h1>Property Binding with Angular</h1>
<h2>Binding the src property of an image:</h2>
<img alt="item" [src]="itemImageUrl">
<hr />
<h2>Binding to the colSpan property</h2>
<table border=1>
<tr><td>Column 1</td><td>Column 2</td></tr>
<!-- Notice the colSpan property is camel case -->
<tr><td [colSpan]="2">Span 2 columns</td></tr>
</table>
<hr />
<h2>Button disabled state bound to isUnchanged property:</h2>
<!-- Bind button disabled state to `isUnchanged` property -->
<button type="button" [disabled]="isUnchanged">Disabled Button</button>
<hr />
<h2>Binding to a property of a directive</h2>
<p [ngClass]="classes">[ngClass] binding to the classes property making this blue</p>
<hr />
<h2>Model property of a custom component:</h2>
<app-item-detail [childItem]="parentItem"></app-item-detail>
<app-item-detail childItem="parentItem"></app-item-detail>
<h3>Pass objects:</h3>
<app-item-list [items]="currentItems"></app-item-list>
<hr />
<h2>Property binding and interpolation</h2>
<p><img alt="Interpolated item" src="{{ itemImageUrl }}"> is the <em>interpolated</em> image.</p>
<p><img alt="Property Bound item" [src]="itemImageUrl"> is the <em>property bound</em> image.</p>
<p><span>"{{ interpolationTitle }}" is the <em>interpolated</em> title.</span></p>
<p>"<span [innerHTML]="propertyTitle"></span>" is the <em>property bound</em> title.</p>
<hr />
<h2>Malicious content</h2>
<p><span>"{{ evilTitle }}" is the <em>interpolated</em> evil title.</span></p>
<!--
Angular generates a warning for the following line as it sanitizes them
WARNING: sanitizing HTML stripped some content (see https://g.co/ng/security#xss).
-->
<p>"<span [innerHTML]="evilTitle"></span>" is the <em>property bound</em> evil title.</p>
</div>

ItemDetailComponent@Input()型がstringであることを確認します。

src/app/item-detail.component.ts (setting the @Input() type)

      
import {Component, Input} from '@angular/core';
// import { Item } from '../item';
// import { ITEMS } from '../mock-items';
@Component({
standalone: true,
selector: 'app-item-detail',
template: `<p>Your item is: {{ childItem }} </p>`,
imports: [],
})
export class ItemDetailComponent {
@Input() childItem = '';
// items = ITEMS;
currentItem = 'bananas in boxes';
}

AppComponentparentItemは文字列なので、[childItem]="parentItem"内の式parentItemは文字列として評価されます。

src/app/app.component.ts

      
import {Component} from '@angular/core';
import {NgClass} from '@angular/common';
import {ItemDetailComponent} from './item-detail.component';
import {ItemListComponent} from './item-list.component';
@Component({
standalone: true,
selector: 'app-root',
templateUrl: './app.component.html',
imports: [ItemDetailComponent, ItemListComponent, NgClass],
styleUrls: ['./app.component.css'],
})
export class AppComponent {
itemImageUrl = '../assets/phone.svg';
isUnchanged = true;
classes = 'special';
parentItem = 'lamp';
currentItems = [
{
id: 21,
name: 'phone',
},
];
interpolationTitle = 'Interpolation';
propertyTitle = 'Property binding';
evilTitle = 'Template <script>alert("evil never sleeps")</script> Syntax';
}

parentItemが他の型であった場合、childItem@Input()もその型として指定する必要があります。

オブジェクトを渡す

この例では、ItemListComponentAppComponentの子コンポーネントであり、itemsプロパティはオブジェクトの配列を期待しています。

src/app/app.component.html

      
<div>
<h1>Property Binding with Angular</h1>
<h2>Binding the src property of an image:</h2>
<img alt="item" [src]="itemImageUrl">
<hr />
<h2>Binding to the colSpan property</h2>
<table border=1>
<tr><td>Column 1</td><td>Column 2</td></tr>
<!-- Notice the colSpan property is camel case -->
<tr><td [colSpan]="2">Span 2 columns</td></tr>
</table>
<hr />
<h2>Button disabled state bound to isUnchanged property:</h2>
<!-- Bind button disabled state to `isUnchanged` property -->
<button type="button" [disabled]="isUnchanged">Disabled Button</button>
<hr />
<h2>Binding to a property of a directive</h2>
<p [ngClass]="classes">[ngClass] binding to the classes property making this blue</p>
<hr />
<h2>Model property of a custom component:</h2>
<app-item-detail [childItem]="parentItem"></app-item-detail>
<app-item-detail childItem="parentItem"></app-item-detail>
<h3>Pass objects:</h3>
<app-item-list [items]="currentItems"></app-item-list>
<hr />
<h2>Property binding and interpolation</h2>
<p><img alt="Interpolated item" src="{{ itemImageUrl }}"> is the <em>interpolated</em> image.</p>
<p><img alt="Property Bound item" [src]="itemImageUrl"> is the <em>property bound</em> image.</p>
<p><span>"{{ interpolationTitle }}" is the <em>interpolated</em> title.</span></p>
<p>"<span [innerHTML]="propertyTitle"></span>" is the <em>property bound</em> title.</p>
<hr />
<h2>Malicious content</h2>
<p><span>"{{ evilTitle }}" is the <em>interpolated</em> evil title.</span></p>
<!--
Angular generates a warning for the following line as it sanitizes them
WARNING: sanitizing HTML stripped some content (see https://g.co/ng/security#xss).
-->
<p>"<span [innerHTML]="evilTitle"></span>" is the <em>property bound</em> evil title.</p>
</div>

ItemListComponent@Input()であるitemsは、Item[]型です。

src/app/item-list.component.ts

      
import {Component, Input} from '@angular/core';
import {NgFor} from '@angular/common';
import {ITEMS} from './mock-items';
import {Item} from './item';
@Component({
standalone: true,
selector: 'app-item-list',
template: `
<h4>Nested component's list of items:</h4>
<ul>
@for (item of listItems; track item) {
<li>{{item.id}} {{item.name}}</li>
}
</ul>
<h4>Pass an object from parent to nested component:</h4>
<ul>
@for (item of items; track item) {
<li>{{item.id}} {{item.name}}</li>
}
</ul>
`,
imports: [NgFor],
})
export class ItemListComponent {
listItems = ITEMS;
@Input() items: Item[] = [];
}

Itemはオブジェクトであり、idnameの2つのプロパティを持つことに注意してください。

src/app/item.ts

      
export interface Item {
id: number;
name: string;
}

app.component.tscurrentItemsは、items.tsItemオブジェクトと同じ形状を持つオブジェクトの配列であり、idnameがあります。

src/app.component.ts

      
import {Component} from '@angular/core';
import {NgClass} from '@angular/common';
import {ItemDetailComponent} from './item-detail.component';
import {ItemListComponent} from './item-list.component';
@Component({
standalone: true,
selector: 'app-root',
templateUrl: './app.component.html',
imports: [ItemDetailComponent, ItemListComponent, NgClass],
styleUrls: ['./app.component.css'],
})
export class AppComponent {
itemImageUrl = '../assets/phone.svg';
isUnchanged = true;
classes = 'special';
parentItem = 'lamp';
currentItems = [
{
id: 21,
name: 'phone',
},
];
interpolationTitle = 'Interpolation';
propertyTitle = 'Property binding';
evilTitle = 'Template <script>alert("evil never sleeps")</script> Syntax';
}

同じ形状のオブジェクトを提供することで、AngularがcurrentItemsの式を評価したときに、itemsの期待を満たします。