いくつかのガイドラインに従うことで、バグを減らし、コードを可読性高く保つことができるようにプロパティバインディングを使用できます。
サイドエフェクトを避ける
テンプレート式の評価は、目に見える副作用があってはなりません。 テンプレート式の構文を使用して、副作用を避けるようにしてください。 一般的に、正しい構文により、プロパティバインディング式で何か他のものへの値の割り当ては不可能になります。 また、インクリメントとデクリメント演算子も使用できません。
サイドエフェクトを生成する例
バインドしているものとは異なるものの値を変更する式があった場合、その値の変更は副作用になります。 Angularは、変更された値を表示するかしない場合があります。 Angularが変更を検出すると、エラーが発生します。
ベストプラクティスとして、値を返すプロパティとメソッドのみを使用してください。
適切な型を返す
テンプレート式は、ターゲットプロパティが期待する型の値を生成する必要があります。 たとえば、次のようなものを返します。
string
:ターゲットプロパティが文字列を期待する場合number
:数値を期待する場合object
:オブジェクトを期待する場合
文字列を渡す
次の例では、ItemDetailComponent
のchildItem
プロパティは文字列を期待しています。
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';}
AppComponent
のparentItem
は文字列なので、[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()
もその型として指定する必要があります。
オブジェクトを渡す
この例では、ItemListComponent
はAppComponent
の子コンポーネントであり、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
はオブジェクトであり、id
とname
の2つのプロパティを持つことに注意してください。
src/app/item.ts
export interface Item { id: number; name: string;}
app.component.ts
のcurrentItems
は、items.ts
のItem
オブジェクトと同じ形状を持つオブジェクトの配列であり、id
とname
があります。
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
の期待を満たします。