web-dev-qa-db-ja.com

コンポーネント入力プロパティでの双方向データバインディング

私はangular2で何かを動作させようとしていますが、この動作について何かを見つけることができません。

私はこのようなカスタムコンポーネントを実装するアプリケーションを持っています:

import {Component,Input} from 'angular2/core'
    @Component({
      selector:'my-comp',
      template:`<input type="text" style="text-align:center; [(ngModel)]="inputText"> <p>{{inputText}}</p>`
    })

    export class MyComp{
      @Input() inputText : string;
    }

そして、次のように、コンポーネントからinputText変数に対して双方向のデータバインディングを実行しようとしています。

<my-comp [(inputText)]="testString"></my-comp>

ここで、testStringは、文字列を含むMyApp.tsで定義された変数です。 testStringがユーザーによって変更されたときに、inputText変数を変更したい。

簡単なサンプルコードを含むプランカーは次のとおりです。 https://plnkr.co/edit/zQiCQ3hxSSjCmhWJMJph?p=preview

これを簡単に機能させる方法はありますか?これをngModelのように機能させるには、カスタムコンポーネントとオーバーロード関数にAngular2クラスを実装する必要がありますか?データが変更されたときにデータを出力するinputTextChangedタイプのEventEmitter変数を作成し、次のようなことを行う必要がありますか?

<my-comp [inputText]="testString" (inputTextChanged)="testString = $event;"></my-comp>

前もって感謝します。

12
David Gonzalez

これは、テンプレート構文ドキュメントの NgModelを使用した双方向バインディング セクションで説明されています。

<input [(ngModel)]="currentHero.firstName">

内部的には、Angularは、用語ngModelngModel入力プロパティとngModelChange出力プロパティにマップします。これはaの特定の例です。 [(x)]をプロパティバインディングのx入力プロパティおよびイベントバインディングのxChange出力プロパティに一致させるより一般的なパターン。

必要に応じて、このパターンに従う独自の双方向バインディングディレクティブ/コンポーネントを作成できます。

[(x)]は、プロパティバインディングとイベントバインディングの単なる構文糖衣であることに注意してください。

_[x]="someParentProperty" (xChange)="someParentProperty=$event"
_

あなたの場合、あなたはしたい

_<my-comp [(inputText)]="testString"></my-comp>
_

したがって、コンポーネントにはinputText入力プロパティとinputTextChange出力プロパティ(EventEmitter)が必要です。

_export class MyComp {
  @Input()  inputText: string;
  @Output() inputTextChange: EventEmitter<string> = new EventEmitter();
}
_

親に変更を通知するには、コンポーネントがinputTextの値を変更するたびに、イベントを発行します。

_inputTextChange.emit(newValue);
_

シナリオでは、MyCompコンポーネントは[(x)]形式を使用して入力プロパティinputTextをngModelにバインドするため、イベントバインディング_(ngModelChange)_を使用して変更を通知し、そのイベントハンドラーで親コンポーネントに変更を通知しました。

NgModelが使用されていない他のシナリオでは、重要なことは、プロパティinputTextの値がMyCompコンポーネントで変更されるたびにイベントをemit()することです。

23
Mark Rajcok

@pixelbitsと@GünterZöchbauerの回答とコメントを組み合わせて、将来誰かがこれを検索している場合は、私の質問に対する明確な回答を作成します。

カスタム変数で双方向データバインディングを機能させるには、以下に基づいてコンポーネントを作成する必要があります。

MyComp.tsファイル:

import {Component,Input,Output,EventEmitter} from 'angular2/core'
@Component({
  selector:'my-comp',
  templateUrl:`<input type="text" style="text-align:center;"
     [ngModel]="inputText" (ngModelChange)="inputText=$event;inputTextChange.emit($event);">`
})

export class MyComp{
  @Input() inputText : string;
  @Output() inputTextChange = new  EventEmitter();
}

MyApp.tsファイル:

import {Component} from 'angular2/core'
import {MyComp} from './MyComp'

@Component({
  selector:'my-app',
  templateUrl:`<h1>Bidirectionnal Binding test </h1>
    <my-comp [(inputText)]="testString"></my-comp><p>
    <b>My Test String :</b> {{testString}}</p>`,
  directives:[MyComp]
})

export class MyApp{
  testString : string;
  constructor(){
    this.testString = "This is a test string";
  }
}

そこでは、inputText変数への双方向データバインディングが正しく機能します。このコードを実装するためのより美しく、より簡単な方法については、回答にコメントすることができます。

8
David Gonzalez

プランカーにはすでにEventEmitterが含まれています。 @Output()アノテーションがありません。値を変更するには、inputTextChanged.emit(newValue)を呼び出します(これにより、inputTextの値も変更されます)

1