インフラジスティックス・ジャパン株式会社のBlog

インフラジスティックス・ジャパン株式会社のチームメンバーが技術トレンド、製品Tips、サポート情報からライセンス、日々の業務から感じることなど、さまざまなトピックについてお伝えするBlogです。

igGrid 動的にセル編集可/不可を制御する

- 2016/08/03(水)時点の情報に基づいています -

 

こんにちは。デベロッパーサポートの桐生です。

弊社のjQuery/HTMl5用コントロールIgnite UIのグリッド igGridの更新機能をお使いで、動的にセルの編集可/不可を制御したい、というお問い合わせがよくありますので、 その方法をご紹介したいと思います。

基本:イベントキャンセルによるセル編集制御

Ignite UI の各コントロールには、大抵の場合において「XXX」の処理をする際の
・前イベントとして「XXXing」イベント
・後イベントとして「XXXed」イベント
が用意されています。
「XXXing」イベントハンドラ内では false を返却することで「XXX」の動作をキャンセルすることができます。

今回の場合 igGridUpdating の editCellStarting イベントを使用して制御を行います。

$('#grid').igGrid({
    width: '600px',
    height: '400px',
    dataSource: dataSource,
    columns: [
        { headerText: 'ID(number)', key: 'id', dataType: 'number', width: '100px' },
        { headerText: 'Name(string)', key: 'name', dataType: 'string', width: '300px' },
        { headerText: 'Flag(bool)', key: 'flag', dataType: 'bool', width: '200px', format: 'checkbox' },
    ],
    primaryKey: 'id',
    features: [
        {
            name: 'Updating',

            // セル編集モード
            editMode: 'cell',

            // nameセル 動的に編集可/不可を切替
            editCellStarting: function(evt, ui) {
                // nameセルでない場合は、編集可
                if (ui.columnKey !== 'name') {
                    return true;
                }

                // 動的に編集可/不可を切り替える
                // 例えば、同じ行のflagセルがチェックONなら編集可、チェックOFFなら編集不可
                var flag = ui.owner.grid.getCellValue(ui.rowID, 'flag');
                if (flag) {
                    // チェックOFFなら編集不可で終了
                    // (false返却でセル編集開始処理がキャンセル = 編集不可)
                    return false;
                }
            },
        },
    ]
});

グリッドには、ID、Name、Flagの3つのセルがあり、それぞれ編集可能となっていますが、
Nameセルは編集可/不可を、Flagセルの値に応じて動的に制御しています。

 

応用:セル編集を制御しつつ、タブ移動を快適にする

上記サンプルでは、 該当セルの編集は確かにキャンセルできるものの、
タブ移動をしている場合、編集がキャンセルされたセルから次のセルへ移動できなくなってしまいます。

期待値としては、編集不可なセルはスキップして、編集可能なセルにのみタブ移動してほしいところです。

この動作を実現してみましょう。

// 動的に編集可/不可を切り替える
// 例えば、同じ行のflagセルがチェックONなら編集可、チェックOFFなら編集不可
var flag = ui.owner.grid.getCellValue(ui.rowID, 'flag');
if (flag) {
    // チェックOFFなら編集不可で終了
    // (false返却でセル編集開始処理がキャンセル = 編集不可)
    return false;
}

の箇所を以下のように変更します。

// 動的に編集可/不可を切り替える
// 例えば、同じ行のflagセルがチェックONなら編集可、チェックOFFなら編集不可
var flag = ui.owner.grid.getCellValue(ui.rowID, 'flag');
if (!flag) {
    // チェックONなら、編集可
    return true;
}

// クリックしてnameセルの編集モードに入ってきた場合
if (evt.originalEvent.type === 'click') {
    // false を返却することにより、編集不可にする。
    return false;
}

// Tabキーを押下してnameセルの編集モードに入ってきた場合
// 次(または前)のセルにスキップさせることにより、編集不可にする。
$(document).one('iggridupdatingeditcellstarted', function (evt2, ui2) {
    // 処理対象が同じでない場合はキャンセル
    if (ui !== ui2) {
        return;
    }

    // Tabキーキーダウン用のEventオブジェクト
    var emulateTabKeyEvent = jQuery.Event('keydown', {
        which: $.ui.keyCode.TAB,
        keyCode: $.ui.keyCode.TAB,
        shiftKey: evt.originalEvent.shiftKey
    });

    // Tabキー(あるいはShift+Tab)キーダウンイベントをトリガーすることにより、次(前)のセルにスキップさせる
    $(ui2.editor.find('input')).trigger(emulateTabKeyEvent);
});

ポイントは、false を返す代わりに、jQueryのEventオブジェクトとtriggerメソッドを使ってタブキーダウンイベントをシミュレートして、該当セルの編集を瞬間的に終了させている点です。
これにより実質的に編集不可にしています。

通常のイベントハンドリングと同様に、タブキーダウンイベントを受けてコントロールが次のセルを探して編集状態にしてくれるので、わざわざ次のセルを探して、編集状態にして、と自前で実装する必要がありません。

 

まとめ

動的に~したい、といった場合には「XXXing」イベントを使用して制御するケースが多いです。
今回は、igGridUpdatingのeditCellStartingを使って制御する方法をご紹介しましたが、
この考え方は他のコントロール、機能においても通ずるものがありますので、ご参考になれば幸いです。