ionicを試す 10日目 *ngForとTable、配列(object)の罠(その1)
前回に引き続き、チェックボックスと*ngForについて試します。
プログラム経験の少ない方には、難易度高めかもしれませんが、ハマりやすい点ともいえると思いますので見て頂ければと思います。(数回に分けたいと思います)
前回までは、*ngForを名前とチェックのあるなしの2項目だけの配列に使用していましたが、項目を増やして表(table)として使う場面が多いような気がします。
また配列の要素数も変更がないケースでしたので、動的に要素数が変わる場合も見ていきたいと思います。
今回は、現実にありそうな状況を考えてみました。
ピザの注文を表にします。
2つの配列を用意します。
片方にはすべてのトッピングが要素として存在するMenu配列。
もう片方には、注文された要素のみからなるOrdered配列。
Menuには、大きなくくりで、”生地”、”ソース”、”トッピング”、”サイド”の区別があり、またそれぞれ商品IDを持ちます。
縦長の表で、右側のメニューを選ぶと左側のオーダーの列に選んだ商品が付け加えられます。
(その際にカテゴリー順、ID順に並べ替えます)
下の様なイメージです。
オーダー済み メニュー
□ナポリ風 〼ナポリ風
□バジルソース □クリスピー
□ペパロニ □ソースレス
□トマトソース
〼バジルソース
〼ペパロニ
□照り焼きチキン
□マッシュルーム
さて、いきなりソースコードをいじります。
(次ページに今回のソースコードを表示しますので参考にしてください)
まず"src\app\home\home.page.html"からですが、テーブル行は1行のみ記述です。(テーブルヘッダーは除く)
とは言え、記述が複雑でとても面倒な感じを受けますので順番に見ていきます。
10行目
---------------------------------------------------------------
<tr *ngFor="let entry of Menu; index as index>
---------------------------------------------------------------
<tr>すなわち行の開始です。前回までは"ion-item"タグの中で使っていましたが、他のタグでも使えます。
今回は
『Menu配列の数だけ、行を表示しろ。何番目の配列要素かを示す"index"も使うぞ。』
という事です。
11行目Order配列のチェックボックスの表示・非表示
---------------------------------------------------------------
<td><ion-checkbox *ngIf="Order.length > index" [(ngModel)]="Order[index].isChecked"></ion-checkbox></td>
---------------------------------------------------------------
Order配列のチェックボックスの表示です。
*ngIfの使用は初めてですが、Angularの機能の一つです。
------------------------------------------
*ngIf="Order.length > index"
------------------------------------------
*ngIf=の次に""で囲まれた部分は、式です。この式の値が真ならば要素を表示(この場合はチェックボックスですね)、そうでないならば、htmlから要素を削除します。
単に表示させ無いという別な機能もありますが、その次の部分で判ると思いますが、この場合はそれではマズいです。
------------------------------------------
[(ngModel)]="Order[index].isChecked"
------------------------------------------
[(ngModel)]は何度か出ていますが、双方向バインディングですね。
"index"番目のOrder配列要素の"isChecked"とチェックボックスをつなげていますので、Order配列の要素数よりも大きなindexを持ってきた場合、エラーが起こります。(この場合、ここから下の表示が行われなず行だけ表示)
ですので、*ngIf=の次の""内の判定式はOrder配列の要素数がindex(0から始まる)よりも大きな時だけ表示させるため、"Order.length > index"になります。
12行目は、同様に表示できるOrder[index].valがあれば表示させるコードです。
------------------------------------------
<td><span *ngIf="Order.length > index">{{Order[index].val}}</span></td>
------------------------------------------
テーブルの整形上、<td>タグの中に<span>タグを仕込んで、そちらの表示・非表示を制御しています。
(直接<td>タグに入れると表示が崩れます)
13~14行目はMenu配列からデータを取ってきていますので、表示・非表示の問題はありませんね。
ただチェックボックスの方に、値が変更した時に動く関数が設定されています。
------------------------------------------
<td><ion-checkbox [(ngModel)]="entry.isChecked" (ngModelChange)="fnChangeCheck(index)"></ion-checkbox></td>
------------------------------------------
関数の定義は"src\app\home\home.page.ts"で行いますが内容は以下の通りです。
------------------------------------------
fnChangeCheck(index:number){
//チェックがついているならば、その要素をOrder配列に追加する
if(this.Menu[index].isChecked){
this.Order.push(this.Menu[index]);
}
------------------------------------------
変更したすべてのファイルを保存して、ブラウザアプリを更新します。
まず、コマンドプロンプトを起動して以下の2つのコマンド入力してください。
(すでに起動しているならば不要です)
------------------------------------------
"cd c:\MyTest\test000"
"ionic serve"
------------------------------------------
4行の列の縦に細長い表が表示されます。左2列はヘッダー以外にデータがありません。
どれでも良いので右側のチェックボックスにチェックを付けてください。
左側の2列に、その行のデータが表示されるのが判ります。
(画面最下部にOrder配列の要素数も表示されていますが0から増えています)
なかなか良い感じですね?
しかし、(関数を見ただけで気づく方は気づくと思いますが)実は大きな問題があります。
次回は、その問題と解決に取り組みます。




