読者です 読者をやめる 読者になる 読者になる

初心者のためのExtJS入門

ExtJSを使うので、ついでにまとめていきます

グリッドの機能:編集[modern]

今回はmodernのグリッド編集を試しました。

とりあえず編集できるようにする

Ext.grid.plugin.Editableが用意されていたので、まずは1カラムだけ編集するようにしてみました。

/**
 * 商品一覧グリッドクラス。
 *
 * @class Sample.view.main.List
 * @extend Ext.grid.Grid
 */
Ext.define('Sample.view.main.List', {
    extend: 'Ext.grid.Grid',
    xtype: 'main_list',

    requires: [
        'Ext.grid.column.Number',
        'Ext.grid.column.Check',
        'Ext.grid.column.Date',
        'Ext.grid.plugin.Editable'
    ],

    title: '商品一覧',

    store: 'Item',

    plugins: 'grideditable',

    columns: [
        {
            dataIndex: 'id',
            text: 'ID',
            align: 'right'
        },
        {
            dataIndex: 'name',
            text: '商品名',
            minWidth: 300,
            flex: 1,
            editable: true
        },
        {
            xtype: 'numbercolumn',
            format:'0,000円',
            dataIndex: 'price',
            text: '金額',
            align: 'right'
        },
        {
            xtype: 'checkcolumn',
            dataIndex: 'isActive',
            text: '有効状況',
            sortable: false
        },
        {
            xtype: 'datecolumn',
            format: 'Y/m/d H:i',
            dataIndex: 'created',
            text: '登録日時',
            width: 180
        }
    ]
});

f:id:sham-memo:20170218213705p:plain

行をダブルタップすると、↑のように編集用のシートが画面右側からスライドインします。

editable: trueとしたカラムだけ、入力フィールドが用意されるようです。

もう少し細かく設定する

もう少し編集シートをカスタマイズしてみました。

/**
 * 商品一覧グリッドクラス。
 *
 * @class Sample.view.main.List
 * @extend Ext.grid.Grid
 */
Ext.define('Sample.view.main.List', {
    extend: 'Ext.grid.Grid',
    xtype: 'main_list',

    requires: [
        'Ext.grid.column.Number',
        'Ext.grid.column.Boolean',
        'Ext.grid.column.Date',
        'Ext.grid.plugin.Editable'
    ],

    title: '商品一覧',

    store: 'Item',

    plugins: {
        type: 'grideditable',

        defaultFormConfig: {
            xtype: 'formpanel',
            scrollable: true
        },

        formConfig: {
            items: [
                {
                    xtype: 'textfield',
                    name: 'name',
                    label: '商品名'
                },
                {
                    xtype: 'numberfield',
                    name: 'price',
                    label: '金額(円)'
                },
                {
                    xtype: 'togglefield',
                    name: 'isActive',
                    label: '有効状況'
                }
            ]
        },

        toolbarConfig: {
            xtype: 'titlebar',
            docked: 'top',
            items: [
                {
                    xtype: 'button',
                    text: 'キャンセル',
                    align: 'left',
                    action: 'cancel'
                },
                {
                    xtype: 'button',
                    text: '更新',
                    align: 'right',
                    action: 'submit'
                }
            ]
        }
    },

    columns: [
        {
            dataIndex: 'id',
            text: 'ID',
            align: 'right'
        },
        {
            dataIndex: 'name',
            text: '商品名',
            minWidth: 300,
            flex: 1
        },
        {
            xtype: 'numbercolumn',
            format:'0,000円',
            dataIndex: 'price',
            text: '金額',
            align: 'right'
        },
        {
            xtype: 'booleancolumn',
            dataIndex: 'isActive',
            text: '有効状況',
            trueText: '有効',
            falseText: '無効',
            align: 'center'
        },
        {
            xtype: 'datecolumn',
            format: 'Y/m/d H:i',
            dataIndex: 'created',
            text: '登録日時',
            width: 180
        }
    ]
});

f:id:sham-memo:20170218214442p:plain

formConfigのitemsコンフィグに入力フィールドを定義することもできるようで、このようにすると、カラムのeditableは不要になるみたいです。

ボタンのテキストを日本語にしてみようと思ったのですが、Ext.grid.plugin.Editableの実装がいけていなくて、DELETEボタンだけは簡単に変更できないようです。

コードを見ると↓のようになっており、textコンフィグに固定文字列が指定されています。

if (me.getEnableDeleteButton()) {
    form.add({
        xtype: 'button',
        text: 'Delete',
        ui: 'decline',
        margin: 10,
        handler: function() {
            grid.getStore().remove(record);
            sheet.hide();
        }
    });
}

オーバーライドクラスで対応

「できません」で終わるのも嫌なので、オーバーライドクラスを作って、その中で対応します。

/**
 * グリッド編集用プラグインクラス。
 *
 * @class Sample.overrides.grid.plugin.Editable
 * @extend Ext.grid.plugin.Editable
 */
Ext.define('Sample.overrides.grid.plugin.Editable', {
    override: 'Ext.grid.plugin.Editable',

    config: {
        /**
         * @cfg {String} 削除ボタンテキスト。
         */
        deleteButtonText: 'DELETE'
    },

    // @override
    onTrigger: function(e) {
        var me = this,
            grid = me.getGrid(),
            formConfig = me.getFormConfig(),
            toolbarConfig = me.getToolbarConfig(),
            record = me.getRecordByTriggerEvent(e),
            fields, form, sheet, toolbar;

        if (record) {
            if (formConfig) {
                this.form = form = Ext.factory(formConfig, Ext.form.Panel);
            } else {
                this.form = form = Ext.factory(me.getDefaultFormConfig());

                fields = me.getEditorFields(grid.getColumns());
                form.down('fieldset').setItems(fields);
            }

            form.setRecord(record);

            toolbar = Ext.factory(toolbarConfig, Ext.form.TitleBar);
            toolbar.down('button[action=cancel]').on('tap', 'onCancelTap', this);
            toolbar.down('button[action=submit]').on('tap', 'onSubmitTap', this);

            this.sheet = sheet = grid.add({
                xtype: 'sheet',
                items: [toolbar, form],
                hideOnMaskTap: true,
                enter: 'right',
                exit: 'right',
                centered: false,
                right: 0,
                width: 320,
                layout: 'fit',
                stretchY: true,
                hidden: true
            });

            if (me.getEnableDeleteButton()) {
                form.add({
                    xtype: 'button',
                    text: me.getDeleteButtonText(),
                    ui: 'decline',
                    margin: 10,
                    handler: function() {
                        grid.getStore().remove(record);
                        sheet.hide();
                    }
                });
            }

            sheet.on('hide', 'onSheetHide', this);

            sheet.show();
        }
    }
});

これで↓のようにdeleteButtonTextを設定します。

/**
 * 商品一覧グリッドクラス。
 *
 * @class Sample.view.main.List
 * @extend Ext.grid.Grid
 */
Ext.define('Sample.view.main.List', {
    extend: 'Ext.grid.Grid',
    xtype: 'main_list',

    requires: [
        'Ext.grid.column.Number',
        'Ext.grid.column.Boolean',
        'Ext.grid.column.Date',
        'Ext.grid.plugin.Editable'
    ],

    title: '商品一覧',

    store: 'Item',

    plugins: {
        type: 'grideditable',

        deleteButtonText: '削除',

        defaultFormConfig: {
            xtype: 'formpanel',
            scrollable: true
        },

        formConfig: {
            items: [
                {
                    xtype: 'textfield',
                    name: 'name',
                    label: '商品名'
                },
                {
                    xtype: 'numberfield',
                    name: 'price',
                    label: '金額(円)'
                },
                {
                    xtype: 'togglefield',
                    name: 'isActive',
                    label: '有効状況'
                }
            ]
        },

        toolbarConfig: {
            xtype: 'titlebar',
            docked: 'top',
            items: [
                {
                    xtype: 'button',
                    text: 'キャンセル',
                    align: 'left',
                    action: 'cancel'
                },
                {
                    xtype: 'button',
                    text: '更新',
                    align: 'right',
                    action: 'submit'
                }
            ]
        }
    },

    columns: [
        {
            dataIndex: 'id',
            text: 'ID',
            align: 'right'
        },
        {
            dataIndex: 'name',
            text: '商品名',
            minWidth: 300,
            flex: 1
        },
        {
            xtype: 'numbercolumn',
            format:'0,000円',
            dataIndex: 'price',
            text: '金額',
            align: 'right'
        },
        {
            xtype: 'booleancolumn',
            dataIndex: 'isActive',
            text: '有効状況',
            trueText: '有効',
            falseText: '無効',
            align: 'center'
        },
        {
            xtype: 'datecolumn',
            format: 'Y/m/d H:i',
            dataIndex: 'created',
            text: '登録日時',
            width: 180
        }
    ]
});

f:id:sham-memo:20170218220325p:plain

こういう対応はExtJSあるあるです。