ionicを試す 15日目 配列の並び替えとテーブル表示の関数使用は可?
だいぶ長引いたピザの注文表もどき、今回で終わらせたいと思います。
残る課題は2つ
解決していない問題点
---------------------------------------------------------------
1.解決
2.解決
3.解決
4.メニューは並び順になっているのにオーダーの順番がバラバラ
5.解決
6.出来れば生地やソース、トッピングなどのカテゴリー別に並べたい
---------------------------------------------------------------
オーダーの並び順を変えるのと、カテゴリーごとにヘッダーをつけたいという要望ですね。
並べ替え(ソート)の方は、配列や連想配列にはそのための手段があらかじめ用意されていますので、それを使います。
オーダー配列に新たな要素を追加した後、各要素の"category_id"と"sub_id"を文字列として連結させた値の大小を比較して並べ替えます。
"src\app\home\home.page.ts"
---------------------------------------------------------------
//配列をソート
this.Order.sort(function(a,b){
if((a.category_id+a.sub_id)<(b.category_id+b.sub_id))return -1;
if((a.category_id+a.sub_id)>(b.category_id+b.sub_id))return 1;
return 0;
});
---------------------------------------------------------------
こういう形で書くと覚えておいてください。
(私も必要になるたび見本を見ています)
次はカテゴリーヘッダーの追加です。
ソートは"src\app\home\home.page.ts"を変更しましたが、ヘッダーの追加は"src\app\home\home.page.html"を変更します。
ポイントとしては、最初の一件と2件目以降では扱いが異なるという事です。
・1件目であれば無条件にカテゴリーヘッダーを表示する。
・2件目であれば、前のカテゴリーIDと比較して異なるならば表示する。
ですので、*ngFromの特殊変数"first"を使います。
さて通常の一つの配列を元に作った表でしたら、これだけで行けると思いますが、メニューとオーダーの二つの配列を使っているこのケースでは、どうなるか?
思考実験をして見ましょう。
まず、今まではメニュー配列要素一つに対して、一つの行が*ngForにより作られました。
オーダー配列がメニュー配列より要素が大きくなることは、仕様上、ありえないのでオーダー配列も順に要素を出力するだけですみました。
基本はメニュー配列のインデックス順に出力し、インデックスがオーダー配列の要素数を超えれば表示しないという形ですね。
---------------------------------------------------------------
<span *ngIf="Order.length > index">{{Order[index].val}}</span>
---------------------------------------------------------------
もう少しお付き合いください。
・メニュー配列のインデックスをmnuIndexとする
・オーダー配列のインデックスをordIndexとする
・ordIndex = fn(mnuIndex)が成り立つ関数がある
上記のindexの部分は、最後のordIndex = fn(mnuIndex) = mnuIndexが単純に成立したからで、カテゴリーヘッダーを追加しても成り立つordIndex = fn(mnuIndex)を定義できるならばそのまま使えるでしょう。
"home.page.html"
---------------------------------------------------------------
<td><span *ngIf="Order.length > fnSimple(index)">{{Order[fnSimple(index)].val}}</span></td>
---------------------------------------------------------------
"home.page.ts"
------------------------------------------
fnSimple(i:number){return i;}
------------------------------------------
もちろん{{Order[fnSimple(index)].val}}の部分も変更が必要ですね。
むしろ表示しない場合は""(長さ0の文字列)を返す方が正解な気もします。
関数外の外部変数として表示済みのオーダー配列の要素数を保持できれば、この方法はうまく行くと思いますので、まず実験してみます。
イメージ
------------------------------------------
削除 注文
生地2 生地1
生地2
生地3
ソース3 ソース1
ソース2
ソース3
トマト オニオン
チーズ
トマト
------------------------------------------
"home.page.ts"
------------------------------------------
//オーダー配列の表示数
public cntOrder =0;
fnSimple(i:number){
this.cntOrder+=1;
return i;
}
------------------------------------------
と実験して、表の末尾にセルを加えてcntOrder を表示すると、ちゃんと増加するのが確認できます。
ただ、その数を見るといきなり90から始まっていますね。
この関数を通過した数だけ増えているのは間違いないでしょうが、根拠が判らないので、末尾のセルに関数fnSimple()の表示を追加します。
今度は、85増えて175から始まります。
もう一つ関数入りセルを増やすと、やはり85増えて260から増えますね。
85はアイテムの数17の5倍ですので、なかなか興味深い話ではありますが、実装には工夫が必要に思えます。
(いずれもF5押下で再読み込みをしての数字です)
具体的には、関数の戻り値を直接Tableで利用するわけにはいかないと判断しました。
表題に偽り有りですね?ただ、方法としては使用可能ですので、場合によっては*ngForを使ったテーブル表示の選択肢には入るとは思います。
ただし、パフォーマンスを考えてだけでもごく単純な例以外は関数を(使えても)使わない方が良いと思われます。
さて、今回。
表示用の配列を用意するのが、堅実と判断しました。
タイミングは最初のコンストラクター(今回は、まだ使われていないですが)とオーダー配列に変更があってソート完了時になりますね。
その表示用配列を見てテーブルの値がセットされるという流れになるかと思います。
コーディング的には配列のグルーピング(カテゴリーIDによる)で行う予定ですが、これは次回に回したいと思います。(てこずったため今回で終わりませんでした)




