LoginSignup
37
33

More than 3 years have passed since last update.

双方向バインディング(ngModel)対応のComponentを自作する

Last updated at Posted at 2017-01-12

Angular2では <input [(ngModel)]="firstName"> と書けば、これを利用してるページでの currentHero.firstName との双方向バインディング(two-way binding)が出来ます。

つまり、スクリプト側で値を変えたら反映されるし、View(つまりHTMLというかDOMというかブラウザ上というか)側で値を変えても、もちろん反映されます。

こういうの、標準の <input>タグとかには Angular側が組み込みで用意してくれているけれども、自作したカスタムコンポーネントではどうする?

答え

@Input() value を作ってるならば
@Output() valueChange = new EventEmitter(); と、同名+ChangeのEventEmitterを作るだけでよい。

そうすると、[(value)] で双方向バインディング出来ます。

ありがちなミス

うまく動かないときは Change"d" になっていないか確認してください。
valueChanged など、 Changed では双方向バインディングできません。

実例

import { Component, EventEmitter, Input, Output } from '@angular/core';

@Component({
  selector: 'input-name',
  template: `
  <div>
    <label>あなたのお名前なんですか?</label>
    <input [value]="name" (change)="change($event.target.value)"></input>
    <button (click)="clear()">クリア</button>
  </div>`
})
export class InputNameComponent {
  @Input()  value: string; // 受け口。 <input-name value="123">と書かれると123が代入される
  @Output() valueChange = new EventEmitter<string>();  // 出力口。

  change(value) { //値が変化した
    this.value = value
    this.valueChange.emit(this.value)
  }

  clear() { //入力値をクリア
    this.value = ""
    this.valueChange.emit(this.value)
  }
}
利用側
<!-- シンプルに書ける -->
<input-name  [(value)]="firstName"></input-name>


<!-- とはいえ、上の書き方はエラー時に混乱しやすいので、こんな風に書いたほうが分かりやすいかも -->
<input-name  [value]="firstName" (valueChange)="firstName=$event"></input-name>

分かってれば簡単だった。

37
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
37
33