Angularのデータバインディングという仕組み

Angularのデータバインディングという仕組み

コンポーネントとビューを紐づけるための仕組みなんですが、コンポーネントって何?って感じです。個人的にはクラスでいいんじゃないかと思っています。ビューはhtmlみたいな。

この二つを合わせてカスタムタグでいいんじゃないかと思っています。<takahashi></takahashi>みたいな。

データバインディングとはこのクラスとhtmlとの間でのデータの変化を伝える仕組みなわけです。

伝えるといっても色々あって、

  • コンポーネント → ビュー
  • ビュー → コンポーネント
  • コンポーネント ⇔ ビュー

と、色々あります。

コンポーネント → ビュー

コンポーネントのプロパティをビューに反映してみます。

dell.component.ts(コンポーネントというかクラス)

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

@Component({
  selector:'app-dell',
  templateUrl:'./dell.component.html',
  styleUrls: ['./dell.component.css']
})
export class DellComponent implements OnInit {

  constructor() { }
  name='takahashi';// コンポーネントのプロパティ
  ngOnInit() {
  }
}

次にコンポーネントのプロパティをビューに反映させます。{{プロパティ}}で表示ができます。

dell.component.html

<span>{{name}}</span>

これで<app-dell></app-dell>としてng serveで起動してみます。

Angularのデータバインディングという仕組み

コンポーネントのプロパティがビューに反映されていることが確認できます。これが、「コンポーネント → ビュー」の型方向通信になります。

他にも色々バインディングする方法が提供されていて、たとえばコンポーネントのプロパティから<a>タグ(なんでも良いが)の属性を反映するプロパティバインディングというのがあります。

dell.component.ts

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

@Component({
  selector: 'app-dell',
  templateUrl: './dell.component.html',
  styleUrls: ['./dell.component.css']
})
export class DellComponent implements OnInit {
  constructor() { }
  url = 'https://www.yahoo.co.jp/';// コンポーネントのプロパティ
  target = '_blank';// コンポーネントのプロパティ
  ngOnInit() {
  }
}

以下のようにビューで記述します。

[href]='プロパティ変数名'

具体的には

[href]='url' // プロパティ名をシングルクォーテーションで囲っても良いし、囲まなくても良い

とします。

dell.component.ts

<a [href]='url' [target]='target'>Yahoo</a>

これで、ng serveで起動すると以下のようにアンカーが表示されます。

Angularのデータバインディングという仕組み

リンクをクリックすると、ヤフーに遷移します。これがプロパティバインディングという仕組みです。

※プロパティバインディングで全ての属性が、同名のプロパティを持っているわけではないのでご注意ください。

属性バインディング

属性をバインドしたい時に使用する仕組みです。

属性はあるが、プロパティがないという属性に対して使用すると思います。

記述方法はプロパティバインディングと良く似ていて、attr.を付けるだけです。

attr.属性名 = 'プロパティ変数名'

dell.component.ts

import { Component, OnInit } from '@angular/core';
@Component({
  selector: 'app-dell',
  templateUrl: './dell.component.html',
  styleUrls: ['./dell.component.css']
})
export class DellComponent implements OnInit {
constructor() { }
  val = 'aiueo';// コンポーネントのプロパティ
  ngOnInit() {
  }
}

dell.component.html

<input type='text' [attr.value]='val' />

value属性はプロパティでもvalueを持っていますが、属性バインディングでもデータを紐づけることができます。

ビュー → コンポーネント

ビュー(画面)でボタンを押したりして、その結果をコンポーネントに情報を渡す仕組みがあります。これもデータバインディングで片方向通信となります。

ビュー(画面)でテキストボックスを表示してみます。onblur時にイベントを実行し、コンポーネントのメソッドを実行させてみます。

dell.component.ts

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

@Component({
  selector: 'app-dell',
  templateUrl: './dell.component.html',
  styleUrls: ['./dell.component.css']
})
export class DellComponent implements OnInit {
  constructor() { }
  val = 'aiueo';
  method(e: any) {
    this.val = e.target.value;
  }
  ngOnInit() {
  }
}

dell.component.html

<input type='text' [value]='val' (blur)='method($event)' /><br>
{{val}}

Angularのデータバインディングという仕組み

主なeventは以下のとおりです。

イベント動作
clickクリック時
blur要素からフォーカスアウト時
input入力時
resetリセット時
submitサブミット時
focus要素にフォーカス時

$event はイベントの色々な情報を持っているオブジェクトになります。引数で指定しておくと、コンポーネント側の引数でイベント内容を渡すことが可能になります。

コンポーネント ⇔ ビュー

双方向通信は、[(ngModel)] を使用します。

dell.component.ts

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

@Component({
  selector: 'app-dell',
  templateUrl: './dell.component.html',
  styleUrls: ['./dell.component.css']
})
export class DellComponent implements OnInit {
  constructor() { }
  val = 'aiueo';
  aaa = ''; // フォーム部品の値と同期している
  ngOnInit() {
  }
}

dell.component.html

<input type='text' [value]='val' [(ngModel)]='aaa' /><br>
{{aaa}}

ngModelディレクティブを使用することによってフォーム部品とコンポーネントのプロパティとを紐づけた場合、同期しているため、input部品のvalue属性の初期値は反映されないので注意です。

ということはコンポーネントのプロパティに初期値を入れておけば、初期値がレンダリングされるはずです。

dell.component.tsを以下のように変更してみます。

dell.component.ts

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

@Component({
  selector: 'app-dell',
  templateUrl: './dell.component.html',
  styleUrls: ['./dell.component.css']
})
export class DellComponent implements OnInit {
  constructor() { }
  val = 'aiueo';// フォーム部品と同期していない
  aaa = 'デフォルト値'; // フォーム部品の値と同期している
  ngOnInit() {
  }
}

初期表示すると以下のように初期値が表示されることが確認できます。

Angularのデータバインディングという仕組み

クラスバインディング

クラスバインディングという仕組みが用意されています。これはHTMLタグにclass属性を追加する仕組みです。

[class.スタイル] = '変数名'

変数名はtrueまたはfalseである必要があります。

例えば、tableタグで作成した表で、クリックした行の背景を変える、というのをクラスバインディングで実装してみます。

app.component.ts

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

@Component({
  selector: 'app-root',
  template:
  `
  <table border="1">
    <tr *ngFor="let tmp of List;let i = index"
      (click)="onColor(i)"
      [class.aaa]="isColor[i]">
      <td>{{tmp.name}}</td>
    </tr>
  </table>
  `,
styles: [`
  tr.aaa{background-color: blue;}
  `]
})
export class AppComponent {
  isColor: boolean[] = [false];// 配列の要素0はデフォルトでfalseを指定しておく
  List = [{'name':'Takahashi'},{'name':'Maruyama'},{'name':'Okuyama'}];
  onColor(i:number) {
    for(let j = 0; j < this.List.length; j++) {
      this.isColor[j] = false;// 全行をいったんfalseにする
    }
    this.isColor[i] = true;// クリックした行のみtrueにする
  }
}

クリックした行のみ背景色が変わります。

Angularのデータバインディングという仕組み

詳細は「AngularとTypeScriptでSPAを作成する」を参照ください。

コメント

タイトルとURLをコピーしました