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
で起動してみます。
コンポーネントのプロパティがビューに反映されていることが確認できます。これが、「コンポーネント → ビュー」の型方向通信になります。
他にも色々バインディングする方法が提供されていて、たとえばコンポーネントのプロパティから<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
で起動すると以下のようにアンカーが表示されます。
リンクをクリックすると、ヤフーに遷移します。これがプロパティバインディングという仕組みです。
※プロパティバインディングで全ての属性が、同名のプロパティを持っているわけではないのでご注意ください。
属性バインディング
属性をバインドしたい時に使用する仕組みです。
属性はあるが、プロパティがないという属性に対して使用すると思います。
記述方法はプロパティバインディングと良く似ていて、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}}
主な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() { } }
初期表示すると以下のように初期値が表示されることが確認できます。
クラスバインディング
クラスバインディングという仕組みが用意されています。これは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とTypeScriptでSPAを作成する」を参照ください。
KHI入社して退社。今はCONFRAGEで正社員です。関西で140-170/80~120万から受け付けております^^
得意技はJS(ES6),Java,AWSの大体のリソースです
コメントはやさしくお願いいたします^^
座右の銘は、「狭き門より入れ」「願わくは、我に七難八苦を与えたまえ」です^^
コメント