この記事ではngModel
を利用せずに、カスタムコンポーネントで双方向バインディングを実現する方法を解説します。
Angularではbanana in a box syntax
を用いることで、双方向バインディングを簡単に実装することが可能です。
目次
banana in a box syntax
とは
banana in a box syntax
とは[(ngModel)]
を利用する際に見かける記法、[()]
の事を指します。
[]
=> box()
=> banana[()]
=> banana in a box
という事です。
[()]
記法は、Angularが備えているテンプレート構文の一種で、プロパティバインディングとイベントバインディングを組み合わせたものと同様の振る舞いをします。
[()]
を用いた場合:
<my-component [(value)]="text"></my-component>
プロパティバインディングとイベントバインディングに分解した場合:
<my-component [value]="text" (valueChange)="text=$event"></my-component>
カスタムコンポーネントの実装例
ここでは要素がクリックされた際に[()]
へ指定された変数が更新されるカスタムコンポーネントを考えます。
まずカスタムコンポーネントを実装します。
@Component({
selector: 'my-component',
template: `<div (click)="onClick()">Hello My Component!</div>`
})
export class MyComponent
{
@Input()
public value: string = '';
@Output()
public valueChange = new EventEmitter<string>();
public onClick(): void
{
this.value = 'Component clicked!';
this.valueChange.emit(this.value);
}
}
上記で実装したカスタムコンポーネントを、利用したいコンポーネントから呼び出します。
@Component({
selector: 'parent-component',
template: `
<my-component [(value)]="text"></my-component>
<pre>{{text}}</pre>
`
})
export class ParentComponent
{
public text: string = '';
}
この状態でparent-component
を呼び出した場合、画面上へはHello My Component!
が表示されます。
そしてHello My Component!
をクリックすると、parent-component
のメンバ変数text
にComponent clicked!
がセットされ画面上に表示されます。
解説
- カスタムコンポーネントは
@Input() public value: string = '';
にてvalue
を受け取ります。 - カスタムコンポーネントは
value
が更新された際、それを親へ伝達するためthis.valueChange.emit(this.value);
を呼び出します。
[(value)]
記法を用いる場合、カスタムコンポーネント側の@Input()
プロパティ名にChange
サフィックスを追加した変数名を、@Output
プロパティとして設定すれば良いわけです。