コンテンツへスキップ
Simplifying Custom Two-Way Data Binding in Angular

Simplifying Custom Two-Way Data Binding in Angular

Angularで双方向のデータバインディングを処理する方法を知っていますか?このハウツーガイドでは、プロセスを簡素化する方法を示します。今すぐ読む。

7min read

Angularのデータバインディングには 3 つのタイプがあり、次のとおりです。

  1. 補完(Interpolation)
  2. イベント バインディング(Event binding)
  3. プロパティバインディング(Property binding)

Angular 1.X のバックグラウンドを持っている場合は、双方向データ バインディングがどこにあるのか疑問に思うかもしれません。AngularJS 1.Xのデモを初めて見たとき、ng-modelの力に圧倒されたことを覚えていますか?はい、あなたと同じように、私もAngularJS 1の双方向データバインディングの能力に非常に感銘を受けました。AngularJS 1の双方向データバインディングは美しかったですが、ダイジェストサイクルと$watchの重荷が伴いました。

物事を単純化するために、Angularには双方向データ バインディングが組み込まれていません。それは意味しません。アプリケーションでは双方向のデータバインディングAngularできません。さあ、双方向のデータバインディングの能力がなければ、最新のWebアプリケーションを作成することは考えられません。そこで、この投稿では、Angularで双方向データバインディングを操作する方法を学びます

Angularには、双方向データバインディングが組み込まれていません

Two-way data binding with ngModel

Angularは、双方向のデータバインディングを実現するためのディレクティブngModelを提供します。以下のリストに示すように、ngModelディレクティブを使用するのは非常にシンプルで簡単です。

import {Component} from '@angular/core';

@Component({
    moduleId:module.id,
    selector:'my-app',
    template:`
  <div class="container">
     <input [(ngModel)]='name' />
      <br/>
      <h1>Hello {{name}}</h1>
  </div>
  `
})
export class AppComponent{


}

ngModelディレクティブを使用するには、アプリケーションにFormsModuleをインポートする必要があります。参考までに、以下に、他の必要なモジュールに加えてFormsModuleをインポートしているapp.module.tsをリストします。

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule }   from '@angular/forms';

import { AppComponent }  from './app.component';

@NgModule({
    imports:      [ BrowserModule,FormsModule ],
    declarations: [ AppComponent],
    bootstrap:    [ AppComponent ]
})
export class AppModule { }

上記のデモでは、入力要素に入力すると、入力の値が name 変数に割り当てられ、ビューにも表示されます。そのため、下の画像に示すように、ngModel を使用して双方向のデータ バインディングを実装しています。

input 要素に入力すると、入力の値が name 変数に割り当てられます

ngModel を使用しない双方向データバインディング

ngModelディレクティブの動作を理解するために、ngModelディレクティブを使用せずに双方向のデータバインディングを実現する方法を見てみましょう。そのためには、

  1. 式を入力要素の値プロパティにバインドするためのプロパティバインディング。このデモでは、名前変数式を値プロパティにバインドしています。
  2. 入力要素で入力イベントを出力するイベントバインディング。はい、ユーザーが入力要素に入力するたびに発生する入力イベントがあります。イベントバインディングを使用すると、入力イベントは式にバインドされます。

したがって、プロパティ バインディングとイベント バインディングを使用すると、次のリストに示すように双方向のデータ バインディングを実現できます。

import {Component} from '@angular/core';

@Component({
    moduleId:module.id,
    selector:'my-app',
    template:`
  <div class="container">
     <input [value]="name" (input)="name=$event.target.value" />
      <br/>
      <h1>Hello {{name}}</h1>
  </div>
  `
})
export class AppComponent{
   name : string = "";
}

このデモのngModelディレクティブデモと同様に、入力要素に入力すると、入力要素の値がname変数に割り当てられ、ビューにも表示されます。

そのため、下の画像に示すコードを使用して、ngModel を使用せずに双方向のデータ バインディングを実装しています。

ngModel を使用せずに双方向データ バインディングを実装する

ここでいくつかの重要なことを理解しましょう。

  1. [value]="name" はプロパティ バインディングです。入力要素の値プロパティを変数(または式)名でバインドしています。
  2. (input)= "expression" はイベントバインディングです。入力イベントが発生するたびに、式が実行されます。
  3. "name=$event.target.value" は、入力された値を name 変数に代入する式です。
  4. Name 変数には、AppComponent クラス内でアクセスできます。

これまで、ngModelを使用した双方向のデータバインディングとngModelを使用しない双方向のデータバインディングを見てきました。ngModel ディレクティブは、プロパティ バインディングとイベント バインディングの組み合わせに他ならないと結論付けることができます。イベントバインディングは小さな括弧で表され、プロパティバインディングは角括弧[]で表され、ngModelの構文が[(ngModel)]であることに気付いた場合は、バナナを箱に入れたようなもので、イベントとプロパティバインディングの両方の組み合わせであることを示唆しています。

ngModel を使用した双方向のデータ バインディングと ngModel を使用しない双方向データ バインディング

Custom two-way data binding

カスタム双方向データバインディングを作成するか、ngModelディレクティブに依存するかに細心の注意を払う必要があります。カスタムの双方向データバインディングを常に作成する必要はありません。ただし、カスタム双方向データバインディングを作成する手順を知っておくとよいでしょう。双方向データバインディングを有効にしたcustomcounterコンポーネントを作成しましょう。手順に従ってください。

Step 1

インクリメントとデクリメントする 2 つのボタンとメソッドを持つコンポーネントを作成します。

@Component({
    moduleId: module.id,
    selector:'countercomponent',
    template:`
    <button (click)='increnent()'>Increment</button>
    {{count}}
    <button (click)='decrement()'>Decrement</button>
    `
})
export class  AppChildComponent {
   count : number = 0;      
   increment(){
       this.count = this.count+1; 
   }
   decrement(){
            this.count = this.count - 1; 
   }
}

上記では、カウントを増減するための非常に単純なコンポーネントを作成しました。これで、このコンポーネントを別のコンポーネント内で使用できますが、このコンポーネントでは双方向のデータバインディングは有効になっていません。 これを有効にするには、@Inputプロパティと@Outputプロパティを使用する必要があります。

Step 2

@Input() プロパティを持つゲッターを作成しましょう。このゲッターはカウントを返します。@Input()デコレータに帰属するため、このコンポーネントのコンシューマーはプロパティバインディングを使用してこの値をバインドできます。

@Input() 
    get counter(){
        return this.count; 
    }

Step 3

双方向のデータバインディングを作成するには、EventEmitter 型のイベントを作成する必要があります。このイベントは、コンシューマコンポーネントに出力できるように@Output()デコレータに帰属します。コンポーネントのコンストラクタにイベントオブジェクトを作成しています。

@Output() counterChange :  EventEmitter<number>;
    constructor(){ 
        this.counterChange = new EventEmitter();        
    }

Step 4

最後のステップとして、インクリメント関数とデクリメント関数は counterChange イベントを発行する必要があります。したがって、以下のリストに示すように、インクリメント関数とデクリメント関数を変更する必要があります。

increment() {
    this.count=this.count+1;
    this.counterChange.emit(this.count);
}

decrement() {
    this.count=this.count - 1;
    this.counterChange.emit(this.count);
}

どちらの関数も counterChange イベントを発行しています。すべての部分をまとめると、カスタム双方向データバインディングを持つコンポーネントは、以下にリストされているコードのようになります。

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

@Component({
    moduleId: module.id,
    selector:'countercomponent',
    template:`
    <button (click)='increment()'>Increment</button>
    {{count}}
    <button (click)='decrement()'>Decrement</button>
    `
})
export class  AppChildComponent {
     count : number = 0;   

     @Output() counterChange :  EventEmitter<number>;
        constructor(){
            this.counterChange = new EventEmitter();      
        }
     
     @Input() 
        get counter(){
            return this.count; 
        }

        increment(){
            this.count = this.count+1; 
            this.counterChange.emit(this.count);
        }

        decrement(){
            this.count = this.count - 1; 
            this.counterChange.emit(this.count);
        }
    }

 

Step 5

他の単純なコンポーネントと同様に、双方向データバインディングを持つコンポーネントは、別のコンポーネント内で使用できます。

import {Component} from '@angular/core';

@Component({
    moduleId:module.id,
    selector:'my-app',
    template:`
  <div class="container">
     <br/>
    
     <countercomponent [(counter)]="c"></countercomponent>
     <br/>
     <h2>count = {{c}}</h2> 
     
  </div>
  `
})
export class AppComponent {
    c : number = 1;  
}

主なことは、カウンタ プロパティの値が AppComponent 内で設定される方法に注意する必要があります。ngModelディレクティブと同様に、counterプロパティもbanana in box構文[(counter])を使用して設定されます

結論

Angularの双方向データ バインディングは、イベント バインディングとプロパティ バインディングによってサポートされます。双方向データバインディングは組み込まれていません。ngModelディレクティブを使用して、双方向のデータバインディングを使用できます。また、必要に応じて、カスタム双方向データバインディングを作成することもできます。カスタム双方向データバインディングは、フォームコントロールで役立ちます。

この投稿では、ngModel とカスタム双方向データ バインディングの作成について学びました。この投稿がお役に立てば幸いです。読んでくれてありがとう。

デモを予約