コンテンツへスキップ
jQuery Grid Checkbox Column Alternatives

jQuery Grid Checkbox Column Alternatives

チェックボックス列(前回のリリースで導入された、Infragistics jQuery Gridでのチェックボックス列の使用に関するこの投稿を参照)は、ブール値を持つ列をチェックボックスに変換するための「ショートカット」を提供するために作成され、顧客からのそのような機能への大きな関心により、ほとんどが現実のものとなりました(そして結局のところ、それは完全に理にかなっています)。

11min read

チェックボックス列(前回のリリースで導入された、Infragistics jQuery Gridでのチェックボックス列の使用に関するこの投稿を参照)は、ブール値を持つ列をチェックボックスに変換するための「ショートカット」を提供するために作成され、顧客からのそのような機能への大きな関心により、ほとんどが現実のものとなりました(そして結局のところ、それは完全に理にかなっています)。

jQuery Grid Checkbox column

もちろん、これは完璧な世界ではなく、すべての人のニーズに合うデフォルトを作成することは、おそらく失われた原因です。上記の紹介ブログを見ると、確かに時間を大幅に節約できます - 必要なのは 1 つのプロパティを設定するだけです。それは良いことですが、そこのコメントや私たちのフォーラムでも見られるように、制限があります - チェックボックス列はうまく機能しますが、テンプレートが関係すると恥ずかしがり屋になります。

問題を

Grid API リファレンスの'renderCheckboxes' の下にある "jQueryTemplating が使用されている場合、そのオプションは利用できません" と書かれています。これは少し誤解を招くだけですが、実際には独自のテンプレートエンジンが含まれているため、間違いなく更新される予定です。したがって、本質的には、上記は「テンプレートが使用されている場合、そのオプションは使用できません」と読む必要があります。これは、設計上、行テンプレートが列に対して独自のレンダリングを持つ可能性があるため、このような場合にチェックボックス列機能が抑制されるためです。

これは、列テンプレートでも利用できない理由についての直感的な説明である場合とそうでない場合がありますが、よく考えてみると、グリッドは行をレンダリングしますが、そのためのデフォルトのテンプレートである行テンプレートがあります。列を定義すると、デフォルトではなく、その行テンプレートのどこかに含まれることになります。そのため、一般的にテンプレートを作成すると、この機能が無効になります。

しかし、心配しないでください、いつものようにオプションがあります。私はこれを偶然見つけ、顧客からのフィードバックがこれを指摘したので(建設的なフィードバックが好きです!)、このブログでは、そのような機能を持つための別の方法を考え出した私の経験を共有します。

ソリューション

Template Checkbox

奇妙なことに、この問題はデータのUI表現を変更する最も簡単な方法であり、好みに合わせて微調整できる非常に柔軟であるため、解決策の主要部分でもあります。これを使用して、すべてが新しい (フォーラム » NetAdvantage for jQuery » igGrid » チェックボックス付きインフラジスティックスIGGrid) であり、前述したように、機能自体はそのためのショートカットです。

公正な警告:私は自分の経験を共有しており、そのために私がとった 2 つの異なるアプローチについて説明します。どちらかを使用する前に、両方を見て検討したことを確認してください。

したがって、最初のアプローチは、checkbox タグ型のプレーンな HTML 入力を使用し、それに値を割り当てることです。これは、上記のリンク先の両方のフォーラム投稿でも見ることができるアプローチです。テンプレートを行テンプレートに適用するか (すでに使用している場合)、単純に 1 つの列に割り当てることができます。デモンストレーションの目的で、AdventureWorks の Employees テーブル (AdventureWorks Sample Databases (MSDN)) を Salaried flag 列に指定すると、グリッド構成は次のようになります。

$("#grid").igGrid({
    primaryKey: "BusinessEntityID",
    height: 550,
    dataSource: "@Url.Action("Employees")",
    autoGenerateColumns: false,
    columns: [
        { key: "BusinessEntityID", width: "50px", headerText: "ID", dataType: "number" , template: "<a style=\'font-size:20px;\' href=\'http://msdn.microsoft.com/en-us/library/ms124432(v=sql.100).aspx\'>${BusinessEntityID}</a>'},
        { key: "LoginID", width: "250px", headerText: "Login ID", dataType: "string" },
        { key: "JobTitle", width: "220px" , headerText: "Job Title", dataType: "string" },
        { key: "SalariedFlag", width: "120px", headerText: "SalariedFlag", dataType: "bool", template: "<input type=\"checkbox\" {{if ${SalariedFlag} === \"true\"}} checked=\"checked\" {{/if}} disabled=\"disabled\" style=\'display: block; margin-left: auto; margin-right: auto;\'>'}
    ],
    features: [
        { name: "Filtering", mode: "advanced", type: "local" },
        { name: "Sorting", type: "local" }]
});

最初の列にはテンプレート(MSDNのまったく同じテーブルの説明へのリンク)もあり、表示されているように、並べ替えやフィルタリングなどの機能で正常に機能することに加えて、チェックボックスの表示を止めることはできません。

テンプレートと単純な HTML 入力タイプのチェックボックスを使用したチェックボックス列の基本的な代替手段。

強化

上記のテンプレートは単なるレンダリングの微調整であり、インタラクションパッケージは付属していません。顧客からのもう1つの公正な指摘は、チェックボックス列が更新するために3回のクリックを必要とするため、デフォルトの操作を改善できることです(これは、選択による行の編集の動作です-1回クリックして選択し、もう1回クリックして編集を入力し、3回目に値を変更することです)。イベントこれは元の問題ではありませんが、チェックボックスを制御できるようになったので、少し改善してみてはいかがでしょうか?

もちろん、最初のステップは無効な部分を取り外すことです。次に、チェックボックスとのユーザー操作を処理する必要があるため、次のようなものを追加します。

data-rowid=\"${BusinessEntityID}\" onchange=\"checkboxChanged(event);\"

テンプレートに追加します。有効なチェックボックス入力の場合、onchangeイベントとclickイベントは基本的に交換可能であるため、いずれかを選択しますが、handleに渡されるパラメータの名前は「event」でなければなりません。'data-'属性は、チェックボックスの場所の情報を格納する最も簡単な方法です - グリッドは、よく見ると行要素で同じことを行い、別の行データエントリにアクセスでき、オーバーヘッドをほとんど追加しないため、作成時に保存する方がはるかに簡単です。これで、更新APIを使用してそのテンプレートを使用するのがいかに簡単かがわかります。

function checkboxChanged(evt) {
    // get rowID where change occured:
    var rowId = $(evt.currentTarget).data().rowid;
    $("#grid").igGridUpdating("updateRow", rowId, { "SalariedFlag": evt.currentTarget.checked });
}

jQuery data()メソッドを使用すると、その行IDがすぐに提供され、渡されたイベントは、その列値に割り当てるチェックボックスの状態を教えてくれます。これには、更新をリソースとしてロードし、グリッド機能(NetAdvantage® jQuery Online Help : igGrid Updating).そして、それはいくつかの問題を引き起こす可能性があります

アップデートがシーンに入ると..。

チェックボックスの編集と更新がすでに関係しているため、グリッドが完全な編集エクスペリエンスを提供することになっていると想定するのはかなり合理的です。ただし、編集モードを有効にすると、編集されたセル/行のUIは別のものになるため、プロバイダーを自分で実装しない場合は、デフォルトのコンボスタイルエディターが表示されます。

編集モードのテンプレートでどうなるか。

これはあなたにとって問題になるかもしれないし、そうでないかもしれないが(編集モードを終了すると正常に動作し、チェックボックスが更新される)、一貫した経験のために、エディターもチェックボックスにすることができればいいでしょう。できれば同じもの。この時点では、かなりの数の選択肢がありますが、実際には、これをより良く、使いやすくする方法をいくつか挙げます。

試してみる小さなトリックの1つは、まったく同じ列を読み取り専用に設定することです。編集状態に関係なくセルの値を設定するコントロールが既にあるため、まったく同じ列を読み取り専用として設定できます。これにより、セルのUIがエディタに置き換えられ、行モードでは変更されないのを防ぐことができます。つまり、上記のようなコンボはなく、同じイベントハンドラーを持つまったく同じチェックボックスがまだアクションの準備ができています。ただし、1つの調整が必要です–Update Rowメソッドは編集セッション内から呼び出されることを意図していないため、UIが更新されます。大丈夫ですか?いいえ。問題は、上記の設定でグリッドがあり、編集がアクティブになっているときに行を更新しようとすると、厄介な動作が保証されることです。UIは更新されます、グリッドがそのグリッドを終了したように見えても、編集セッションの編集を処理するボタンやその他の要素がないため、 編集はアクティブなままです。まあ、行き詰まっています。ここには、更新行を呼び出す前に編集を終了するなどのオプション(もちろんメソッドが利用可能)が表示されますが、チェックボックスの変更ですぐに終了し、おそらくユーザーが期待していることではありません。繰り返しになりますが、編集中にチェックボックスを無効にすることもできますが、編集がアクティブな場合はそうではありません。

チェックボックスがその UI を処理する後、変更をデータソースのトランザクションログに直接保存することもできますが、他の機能で適切に動作するには追加の作業 (データダーティイベント、再バインド) が必要になる場合があります。また、ユーザーに対してまったく同じ行で編集を再開することもできます。

function checkboxChanged(evt) {
    // get rowID where change occured:
    var rowId = $(evt.currentTarget).data().rowid;
    // if editing is active - update just the cell, otherwise use row update
    if($("#grid").igGridUpdating("isEditing")){
        $("#grid").igGridUpdating("endEdit");
        $("#grid").igGridUpdating("setCellValue", rowId, "SalariedFlag", evt.currentTarget.checked);
         
        //optionally can start the editing on the same row again
        //need row index:
        var rows = $("#grid").igGrid("rows");
        var rowIndex;
        //var context = this;
        $.each(rows, function (index, row) {
            if ($(row).data().id == rowId) {
                rowIndex = index;
            }
        });
        //make sure you let the calling code exit before attempting start edit,
        // a few milliseconds should be enough
        setTimeout(function () { $("#grid").igGridUpdating("startEdit", rowIndex, 1); }, 2);
    }
    else {
        $("#grid").igGridUpdating("updateRow", rowId, { "SalariedFlag": evt.currentTarget.checked });
    }
}

上記のスニペットは、IDから行インデックスを取得し、その行の編集を少し遅れて開始することを示しています(イベントハンドラは、他の場所の匿名関数内で呼び出されます)。編集を終了して開始すると、UIが変更され、わずかなちらつきが発生しますが、ある程度の欲求とCSSの微調整により変更できます。

さらに優れたエクスペリエンスを得るためにカスタム エディター プロバイダーを作成する可能性を検討できることに注意してください。

No Boolean? No problem!

ここまで、実際の値と表現の間には非常に弱い関係があることに気付いた方もいらっしゃると思いますが、私たちのロジックは表現と相互作用の結果の両方を決定します。したがって、ブール値(文字列、数値、null値)以上のものを使用することを実際に妨げるものは何もありません。おそらく、チェックボックスの2つ以上の状態も調べてください。AdventureWorks の SpecialOffers テーブルで、各オファーの MaxQty プロパティに最大値 OR 'NULL' が記載されているとします。そのデータを表示するだけでなく、その評価結果を表示したいと考えています。最良の例ではないかもしれませんが、代わりにオファーに最大値があるかどうかを示す列があります。

$.ig.loader(function () {
    $("#grid").igGrid({
        primaryKey: "SpecialOfferID",
        height: 550,
        dataSource: "@Url.Action("SpecialOffersData")",
        autoGenerateColumns: false,
        columns: [
            { key: "SpecialOfferID", width: "100px", headerText: "ID", dataType: "number" , template: "<a style=\'font-size:20px;\' href=\'http://msdn.microsoft.com/en-us/library/ms124455(v=sql.100)\'>${SpecialOfferID}</a>'},
            { key: "Description", width: "250px", headerText: "Description", dataType: "string" },
            { key: "Type", width: "220px" , headerText: "Type", dataType: "string" },
            { key: "MaxQty", width: "150px", headerText: "Has MaxQty", dataType: "string", template: "<input type=\"checkbox\" {{if parseInt(${MaxQty}) }} checked=\"checked\" {{/if}} data-rowid=\"${SpecialOfferID}\"  data-test=\"${MaxQty}\" onchange=\"checkboxChanged(event);\" style=\'display: block; margin-left: auto; margin-right: auto;\'>'}
        ],
        features: [
            { name: "Filtering", mode: "advanced", type: "local" },
            { name: "Sorting", type: "local" },
            { name: "Updating"}]
    });
});

このチェックボックスは、値が 'false' に相当するものの 1 つでない場合にのみオンになっていることに注意してください (解析は、たとえば失敗した場合に NaN を返します)。また、ほぼ同じ方法で値を設定できます - falseにはnullを追加し、trueにはデフォルト/計算値を追加します。

function checkboxChanged(evt) {
    // get rowID where change occured:
    var rowId = $(evt.currentTarget).data().rowid;
    var newValue = evt.currentTarget.checked ? 10 : null;
    $("#grid").igGridUpdating("updateRow", rowId, { "MaxQty": newValue });
}

結果 (SQL Management Studio と jQuery Grid を使用して実行中のアプリの両方から):

チェックボックステンプレートを使用すると、ブール値以外の値を簡単に表示できます。

そして、ここでも、前述の更新トリックを同じ方法で実装できます。

進んでいます

DIY テンプレートとデフォルトのチェックボックス列の簡単な比較は次のとおりです。

PROS

  • 他のテンプレートで動作します。
  • 実装が簡単 – 単純なシナリオの場合は 1 行。
  • ブール値だけに限定されません。
  • カスタムソリューションとして、バイステートチェックボックスに限定されず、トライステートチェックボックスを実装できる可能性があります(単純な 3 状態のチェックボックスの実装を示す JSFiddle。)

短所

  • 同様の結果を得るには、いくつかのコードが必要です。
  • 更新編集モード内でも機能する必要がある場合は、実装がやや複雑になる可能性があります。全体的に、更新機能とのトリッキーな関係にあります。
  • ブラウザの実装は特別なものではなく、(間違っている場合は訂正してください)同じように見えることも保証されていません。


この経験が、デフォルトが提供できるという点で、より優れた機能を念頭に置いているすべての人に役立つことを願っています。上で述べたように、これは私が経験を共有しているだけであり、ここには学習曲線があり、これが唯一または最終的な解決策ではありません。今後のブログで別のアプローチにご期待ください。

デモプロジェクトはダウンロード可能です.いつものように、Twitterでフォローできます@DamyanPetevそして@Infragistics連絡を取り合うフェイスブック,Google+のそしてLinkedInの!

デモを予約