w2uiのグリッド(w2grid)でソートを使う際に、時間などのテキストをソートしたい場合に思うようにいかなかったのでその対策を書きます。
たとえば「一週間の稼働時間を一覧で表示する」としましょう。DBにはユーザー名と稼働時間として「分」のデータが入っているとします。
下記はDBから取得したデータを配列化したものです。
/**
* データ
* totalは「分」を表しています。
* totalを表示上はhh:mm形式で表示し、裏では「分」のままで扱うことで、正しくソートさせます。
*/
$data = array(
array('recid' => 1, 'name' => 'John Doe', 'total' => 100,),
array('recid' => 2, 'name' => 'Stuart Motzart', 'total' => 120,),
array('recid' => 3, 'name' => 'Jin Franson', 'total' => 60,),
array('recid' => 4, 'name' => 'Susan Ottie', 'total' => 8,),
array('recid' => 5, 'name' => 'Kelly Silver', 'total' => 600,),
array('recid' => 6, 'name' => 'Francis Gatos', 'total' => 25,),
array('recid' => 7, 'name' => 'Mark Welldo', 'total' => 1520,),
array('recid' => 8, 'name' => 'Thomas Bahh', 'total' => 660,),
array('recid' => 9, 'name' => 'Sergei Rachmaninov', 'total' => 99,),
);
PHPデータを取得・整形し、JSON形式でJSに渡すことは難しくないでしょう。配列をJSON形式に変換するだけであればjson_encode($data);
で変換できます。
ただ、このままでは稼働時間が「時間(分)」の数値として表示されてしまいます。稼働時間の一覧なのでhh:mm
形式で表示したいものです。ではPHPで配列を整形する時にhh:mm
形式に変換して配列に格納すればよいでしょうか。しかし、そう簡単にはいきません。
結果を「時間(分)」でソートをしたい場合、hh:mm
形式ではテキストとして扱われてしまい上手くソートすることが出来ず不都合です。正しいソートを実現するにはどのようにすればよいでしょうか。公式サイトで以下のような記述がありました。
I see your problem. Here is how I would do.
1. Date field should be in some sortable format (a) unix time, which is number of milliseconds from 1970 or (b) in the format YYY/MM/DD - then as a string it is sortable. If your date in any of this formats it will be sortable.
2. You need a user render property for the column. In fact in current master, there is one.
In current master you can find example in test/grid.html. It uses first approach, plus in addition it has search fields that allow you to search by date.
引用 - http://w2ui.com/ (http://disq.us/p/nll7qa)
ソート用のデータを持ちつつ、表示用はrender
プロパティを使って表示せよ。とのことです。
render
プロパティはパラメータを2種類の方法で渡すことができます。
- 予め決められたフォーマットを渡す
- 値を整形するためのfunctionを指定する
つまり、PHPでは「時間(分)」を整形せず、render
プロパティにfunction
として「時間(分)」をhh:mm
形式に変換する処理を入れればよさそうです。
/**
* 列データ
* 列ごとの設定です。この配列をJSONに変換してJSに渡します。
*/
$columns = array(
array('field' => 'name', 'caption' => 'Name', 'size' => '50%', 'sortable' => true,),
array(
'field' => 'total', 'caption' => 'total', 'size' => '50%', 'sortable' => true,
/**
* 表示用の計算
* 「分」からhh:mmに変換
*/
'render' => 'function (record) {
var total = record.total,
h, m;
h = Math.floor(total / 60);
m = total % 60;
if (String(m).length == 1) {
m = "0" + String(m);
}
return h + ":" + m;
}',
),
);
ここで問題が発生します。columns
をPHPで生成している場合、この方法はできません。なぜなら、PHPでrender
プロパティを含めたJSONを生成すると、render
プロパティの処理(JSのfunction)が文字列として渡されてしまうからです。そこでFunction.call()
を使います。
DATA = {
columns : <?php echo json_encode($columns)?>,
data : <?php echo json_encode($data)?>,
}
//total列のrenderをfunctionとして書き換えます。
DATA.columns[1].render = Function.call(null, "return " + DATA.columns[1].render)();
※DATA.columns
、DATA.data
の取得は説明用に1つのPHPファイルで書く為に単純化しています。ご利用のフレームワークや、APIに応じて書き換えることをおすすめします。
render
プロパティの中身を文字列からJSに書き換えた状態でw2gridを生成すれば、表示も正しく、ソートも出来るということになります。
$('#myGrid').w2grid({
name : 'myGrid',
columns: DATA.columns,
records: DATA.data,
});
今回説明で利用したソースはこちらにあります。