Angular Webアプリ開発入門14

はじめに

今回はFormBuilderを使ったFormCpontorolを構成する方法でラジオボタンやチェックボックス追加する。

完成ページ

完成ページ

ラジオボタンに関連付けるFormControlを作る

TypeScriptのプログラムを修正し名目をhotcoldとし、その初期値とする。
そのために下記のように、赤字の部分を記述する。

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

import {FormControl,FormGroup,FormBuilder }from‘@angular/forms’;

@Component({

selector: ‘app-controls’,

templateUrl: ‘./controls.component.html’,

styleUrls: [‘./controls.component.css’]

})

export classControlsComponentimplementsOnInit {

coffeeForm:FormGroup;

constructor(privatefb:FormBuilder) {

this.coffeeForm=this.fb.group({

name: ブレンド,

taste: バランスのよい口当たり,

hotcold:“Hot”

});

}

ngOnInit() {

}

}

 

ラジオボタンの入力フォーム作る

ラジオボタンを構成する入力フォームを作る。
value属性は、そのラジオボタンが選択された時の値で、それぞれ「Hot」と「Cold」を設定している。
ラジオボタンでもformControlName属性でどの名前のFormControlと結びつけるかを設定する。
ここではどちらも「hotcold」に設定している。下記のように複数のラジオボタンに同じFormContorolを結びつけると、そのうち一方しか選べないという状態になる。

h2>コーヒー品目リスト作成</h2>

<form[formGroup] =“coffeeForm”novalidate>

<div>

<label>品名:<inputformControlName=“name”></label>

</div>

<div>

<label>テイスト:<inputformControlName=“taste”size=“50”></label>

</div>

<div>

<span>

<inputtype=“radio”formControlName=“hotcold”value=“Hot”>Hot

</span>

<span>

<inputtype=“radio”formControlName=“hotcold”value=“=”Cold>Cold

</span>

</div>

</form>

<p>フォーム入力値:{{coffeeForm.value | json}}</p>

*ngForで繰り返し処理を書く

ラジオボタンの数だけ、<input type “radio”…>と並べるのは選択肢が多い時は効率的ではない。
選択肢を配列として用意しておき、それをループで出力するのは一般的である。

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

import {FormControl,FormGroup,FormBuilder }from‘@angular/forms’;

@Component({

selector: ‘app-controls’,

templateUrl: ‘./controls.component.html’,

styleUrls: [‘./controls.component.css’]

})

export classControlsComponentimplementsOnInit {

coffeeForm:FormGroup;

hotcoldsel=[“Hot”, “Cold”];

constructor(privatefb:FormBuilder) {

this.coffeeForm=this.fb.group({

name: ブレンド,

taste: バランスのよい口当たり,

hotcold:this.hotcoldsel[0]

});

}

ngOnInit() {

}

}

選択肢をループ処理で繰り返し出力する

<h2>コーヒー品目リスト作成</h2>

<form[formGroup] =“coffeeForm”novalidate>

<div>

<label>品名:<inputformControlName=“name”></label>

</div>

<div>

<label>テイスト:<inputformControlName=“taste”size=“50”></label>

</div>

<div>

<span *ngFor=”let state of hotcoldsel”>

<input type=”radio” formContorolName=”hotcolds” [value]=”state”>{{state}}

</span>

</div>

</form>

<p>フォーム入力値:{{coffeeForm.value | json}}</p>

 

*ngForでは、”let state of hotcoldset”という値を指定している。これは「hotcoldsetから一つずつ取り出し、その値をstateに格納して繰り返す」という意味である。hotcoldsetは、TypeScriptのプログラムの方で、配列として「Hot」と「Cold」が指定されている。つまり、stateに「Hot」と「Cold」の値は順に設定され、計2回出力される。ラジオボタンはspan要素の中で次のように指定している。

<inputtype=“radio”formContorolName=“hotcolds”[value]=“state”>{{state}}

「{{state}}」というのは「{{」と「}}」で囲まれているので、stateの中身を表示するという意味である。

チェックボックスを追加する

次にチェックボックスを作る。チェックボックスはラジオボタンと比べると処理が複雑である。その理由は、ラジオボタンどれか一つしか選択しないのに対して、チェックボックスは複数選択する可能性があるからである。
つまり、ラジオボタンは全部で1つのFormContorolに結びつければよいが、チェックボックスは選択された複数のFormControlに結びつけなければならない。しかも選択されたものだけがFormControlにに結びつけられるので、その数が可変である。

チェックボックスを実装する場合の考え方

①FormControlを空の配列として用意する
FormControlに含まれるFormControlは、FormBuilderを使って空の配列を用意する。

②チェックの状態によって①の配列を追加したり削除したりする
それぞれのチェックボックスに対して、チェックの状態が変わったときのイベントを設定することで、状態が変わった時に指定することで、状態が変わった時に指定した処理が実行されるようにする。
その処理の中では「チェックされている」か「チェックされていないか」を調べ、チェックされている時は、その値を①の配列に追加する。チェックされていない時は①の配列から除去する。

チェックボックスを描画する

①選択肢をプロパティとして用意する

addssel=[“Milk”,“Sugar”]

②チェックボックスの状態を保存する空のFormControl配列を用意する。
FormBuilderを使って「fb.array([])」のように記述する。ここではaddsという名前でテンプレートから参照できるようにする。

adds: this.fb.array([])

 

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

import {FormControl,FormGroup,FormBuilder }from‘@angular/forms’;

@Component({

selector: ‘app-controls’,

templateUrl: ‘./controls.component.html’,

styleUrls: [‘./controls.component.css’]

})

export classControlsComponentimplementsOnInit {

coffeeForm:FormGroup;

hotcoldsel=[“Hot”,“Cold”];

addssel=[“Milk”, “Sugar”]

constructor(privatefb:FormBuilder) {

this.coffeeForm=this.fb.group({

name: ブレンド,

taste: バランスのよい口当たり,

hotcold:this.hotcoldsel[0],

adds: this.fb.array([])

});

}

ngOnInit() {

}

}

ループで処理してチェックボックスを表示する

次にテンプレートを変更し、チェックボックスを表示するようにする。それにはラジオボタンと同様に*ngFor属性を使う。ここでは、FormControlName属性は指定しない点に注意する。この実装ではFormGroupに直接結びつけるのではなく、チェックボックスが変わった時に、その処理の中でFormGroup配下のFormControlを操作するので結びつけずに切り離しておく。

<h2>コーヒー品目リスト作成</h2>

<form[formGroup] =“coffeeForm”novalidate>

<div>

<label>品名:<inputformControlName=“name”></label>

</div>

<div>

<label>テイスト:<inputformControlName=“taste”size=“50”></label>

</div>

<div>

<span*ngFor=“let state of hotcoldsel”>

<inputtype=“radio”formContorolName=“hotcold”[value]=“state”>{{state}}

</span>

</div>

<div>

<span*ngFor=“let item of addssel”>

<inputtype=“checkbox”>{{item}}

</span>

</div>

</form>

<p>フォーム入力値:{{coffeeForm.value | json}}</p>

チェック状態が変わった時にメソッドが実行されるようにする

チェック状態が変わった時に処理を実行するために、チェックボックスの構成を変更して、状態が変わった時にメソッドが実行されるようにする。
この方法は、ボタンがクリックされたときに使った「(click)=メソッド名」の表記と似ていて「(change)=メソッド名」という表記で行う。

<h2>コーヒー品目リスト作成</h2>

<form[formGroup] =“coffeeForm”novalidate>

<div>

<label>品名:<inputformControlName=“name”></label>

</div>

<div>

<label>テイスト:<inputformControlName=“taste”size=“50”></label>

</div>

<div>

<span*ngFor=“let state of hotcoldsel”>

<inputtype=“radio”formContorolName=“hotcold”[value]=“state”>{{state}}

</span>

</div>

<div>

<span*ngFor=“let item of addssel”>

<input type=”checkbox” (change)=”onCheckChanged(item,$event.target.checked)”>{{item}}

</span>

</div>

</form>

<p>フォーム入力値:{{coffeeForm.value | json}}</p>

 

チェック状態が変わったときにFormControlオブジェクトとして設定する

次にチェックの状態が変わったときに実行されるように設定したonCheckChangedメソッドをTyoeScriptのプログラムとして実装する。

 

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

import {FormControl,FormGroup,FormBuilder }from‘@angular/forms’;

import { FormArray } from ‘@angular/forms/src/model’;

@Component({

selector: ‘app-controls’,

templateUrl: ‘./controls.component.html’,

styleUrls: [‘./controls.component.css’]

})

export classControlsComponentimplementsOnInit {

coffeeForm:FormGroup;

hotcoldsel=[“Hot”,“Cold”];

addssel=[“Milk”,“Sugar”]

constructor(privatefb:FormBuilder) {

this.coffeeForm=this.fb.group({

name: ブレンド,

taste: バランスのよい口当たり,

hotcold:this.hotcoldsel[0],

adds: this.fb.array([])

});

}

ngOnInit() {

}

onCheckChanged(item:string, isCheacked:boolean){

let formArray = <FormArray>this.coffeeForm.controls.adds;

if(isCheacked){

formArray.push(new FormControl(item));

}else{

let index = formArray.controls.findIndex(elm => elm.value == item)

formArray.removeAt(index);

}

}

}


onCheckChangedメソッドは次のように定義している。ここで渡されるitemとisCheakedはmそれぞれテンプレート側で指定したitemと$event.target.cheackedに相当する。すなわちitemには「Milk」や「Sugar」、isCheckedには「チェックがつけられているかどうかの状態」が設定される。

onCheckChanged(item:string,isCheacked:boolean){

処理

}

まずは現在のFormContorol配下のaddsの状態を取得する。これはFormArrayオブジェクトの配列として参照できる。

letformArray = <FormArray>this.coffeeForm.controls.adds;

 

なお、FormArrayを利用するにはインポートしておく。

import {FormArray }from‘@angular/forms/src/model’;

 

チェックがついているときには、このFormArrayにFormControlオブジェクトを追加し、チェックがつけられていないときは、FormArrayからFormControlオブジェクトを除外する。

if(isCheacked){

formArray.push(newFormControl(item));

}else{

letindex =formArray.controls.findIndex(elm=>elm.value ==item)

formArray.removeAt(index);

}

終わりに

ラジオボタンは全部で1つのFormContorolに結びつければよい。

チェックボックスは選択された複数のFormControlに結びつけなければならない。しかも選択されたものだけがFormControlにに結びつけられるので、その数が可変である。

今回はラジオボタンとチェックボックスの作成方法について学んだ。次回はドロップダウンリストについて学び、今まで学んだFormBuilderを使ったFormCpontorolを構成する方法について整理し、まとめていく。

 

コメント