Taste of Tech Topics

Acroquest Technology株式会社のエンジニアが書く技術ブログ

jqGridでExcelみたいにグループ化する方法


みなさん、こんにちは。
fujiiです。

今回はライブラリをちょっと応用して、
jqGrid上でExcelのグループ化機能を作りたいと思います。

調査

まずはjqGridで使えそうな機能がないかと探していたら、使えそうなのが見つかりました。
showCol、hideColというメソッドがあります。

引数はcolnameとなっているので、どうやらカラム名を指定すればよいようです。

使い方はこんな感じです。

$('#sample1').jqGrid('showCol', 'age');

上記のようにカラム名を指定すればできそうですが、
固定でカラムを指定するのはいまいち芸がないので、
設定によってグループ化するフィールドを変更してみましょう。

//列の設定
var colModelSettings= [	
  {name:"No.",index:"No.",width:70,align:"center",classes:"no_class",sortable:true,sorttype:'text'},
  {name:"name",index:"name",width:70,align:"center",classes:"name_class",sortable:true,sorttype:'text'},
  {name:"age",index:"age",width:70,align:"center",classes:"age_class",group:true},
  {name:"local",index:"local",width:70,align:"center",classes:"local_class",group:true},
  {name:"hobby",index:"hobby",width:70,align:"center",classes:"hobby_class"},
  {name:"sex",index:"sex",width:70,align:"center",classes:"sex_class"}
];
// グループ化を行う列を取得する。
createGroupArray = function(settings) {
  var groupArray = new Array();
  $.each(settings, function(index, data) {
    if (data.group == true) {
      groupArray.push(data.name);
    }});
  return groupArray;
};
// グループ化する列を設定
var groupArray = createGroupArray(colModelSettings);

グループ化してみよう

準備はできたので、グループ化を行います。

doGroup = function(show) {
  $.each(groupArray, function(index, data) {
    if (show == true) {
      $('#sample1').jqGrid('showCol', data);
    } else {
      $('#sample1').jqGrid('hideCol', data);
    }});
}

グループ化時には引数にfalseを、展開時には引数にtrueを指定すれば、
グループ化/グループ化解除が確認できました。

注意点

これでグループ化完成。と思っていたら大きな落とし穴が。
どうやらこの方法はデータを増やすとあまり性能が出ないようです。

原因を調べてみようとjqGridのソースを見てみると、原因が分かりました。

どうやらshowColもhideColも内部で呼ばれているメソッドの最後に、
幅を再計算していますね。
つまりは、showColもhideColも呼べば呼ぶほど、性能が出ないようです。

hideCol : function (colname) {
  return this.each(function(){$(this).jqGrid("showHideCol",colname,"none");});}
showCol : function(colname) {
  return this.each(function(){$(this).jqGrid("showHideCol",colname,"");});},
showHideCol : function(colname,show) {
  return this.each(function() {
    var $t = this, fndh=false, brd=$.browser.webkit||$.browser.safari? 0: $t.p.cellLayout, cw;
    if (!$t.grid ) {return;}
    ・・・
      }
    });
    if(fndh===true) {
      $($t).jqGrid("setGridWidth",$t.p.shrinkToFit === true ? $t.p.tblwidth : $t.p.width ); //★ここがポイント
    }
    if( gh )  {
      $($t).jqGrid('setGroupHeaders',$t.p.groupHeader);
    }
  });

というわけで、このメソッドを何度も呼ばなくて済む方法がないか調べてみたところ、分かりました。
引数のcolnameは配列もしていできるようです。

改善版

改善版がこちら。
かなりシンプルにかけました。

doGroup = function(show) {
  if (show == true) {
    $('#sample1').jqGrid('showCol', groupArray);
  } else {
    $('#sample1').jqGrid('hideCol', groupArray);
  }
};

後は好きなボタンでもつけて、メソッドを呼び出せば完成です。
サンプルソースはこちらから。
jqGrid_grouping.zip 直