Ext.dashboard.Dashboardを使うと、業務系の画面でよくあるダッシュボードのUIを実現できます。

partsコンフィグに、適当なキー名でExt.dashboard.Partクラスのコンフィグを指定します。

さらにExt.dashboard.PartのviewTemplateコンフィグのitemsに表示したいビューを指定することになります。

まだpartsコンフィグだけでは表示されないです。

defaultContentコンフィグには、最低限typeとcolumnIndexを指定したオブジェクトリテラルの配列を指定します。

ここでtypeはpartsコンフィグで指定したキー名、columnIndexは列のインデックス番号(0から)です。

/**
 * ダッシュボードパネルクラス。
 *
 * @class Sample.view.main.dashboard.Panel
 * @extend Ext.dashboard.Dashboard
 */
Ext.define(Sample.view.main.dashboard.Panel, {
    extend: Ext.dashboard.Dashboard,
    xtype: main_dashboard_panel,

    parts: {
        testKey: {
            viewTemplate: {
                items: {
                    xtype: panel,
                    html: パネル
                }
            }
        }
    },

    defaultContent: [
        {
            type: testKey,
            columnIndex: 0
        },
        {
            type: testKey,
            columnIndex: 1
        },
        {
            type: testKey,
            columnIndex: 2
        },
        {
            type: testKey,
            columnIndex: 1
        }
    ]
});

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

上記だと、testKeyのビューを4つダッシュボードに表示しています。columnIndex=1を2つ指定しているので、2列目のビューは2つになっています。

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

ドラッグ&ドロップ操作で場所を移動させることができます。

動的にビューを追加する

ボタンクリック時にビューを追加してみます。

/**
 * ダッシュボードパネルクラス。
 *
 * @class Sample.view.main.dashboard.Panel
 * @extend Ext.dashboard.Dashboard
 */
Ext.define(Sample.view.main.dashboard.Panel, {
    extend: Ext.dashboard.Dashboard,
    xtype: main_dashboard_panel,

    parts: {
        testKey: {
            viewTemplate: {
                items: {
                    xtype: panel,
                    html: パネル
                }
            }
        }
    }
});

/**
 * メインパネル。
 *
 * @class Sample.view.main.Panel
 * @extend Ext.panel.Panel
 */
Ext.define(Sample.view.main.Panel, {
    extend: Ext.panel.Panel,
    xtype: main_panel,

    requires: [
        Sample.view.main.dashboard.Panel,
        Sample.view.main.ViewController
    ],

    controller: main,

    cls: main-panel,

    layout: fit,

    dockedItems: {
        xtype: toolbar,
        items: [
            ->,
            {
                text: 追加,
                handler: onClickAddButton
            }
        ]
    },

    items: {
        reference: dashboard_panel,
        xtype: main_dashboard_panel
    }
});

/**
 * ビューコントローラクラス。
 *
 * @class Sample.view.main.ViewController
 * @extend Ext.app.ViewController
 */
Ext.define(Sample.view.main.ViewController, {
    extend: Ext.app.ViewController,
    alias: controller.main,

    onClickAddButton: function () {
        var me = this,
            dashboardPanel = me.lookupReference(dashboard_panel);

        dashboardPanel.addNew(testKey, 0);
    }
});

Ext.dashboard.DashboardのaddNewメソッドで追加できます。第1引数はpartsコンフィグに定義したキー名、第2引数は列のインデックス番号です。

でも、これだとpartsコンフィグに定義されていない呼び出せないです。なので、partsコンフィグにも動的に追加してみます。

/**
 * ダッシュボードパネルクラス。
 *
 * @class Sample.view.main.dashboard.Panel
 * @extend Ext.dashboard.Dashboard
 */
Ext.define(Sample.view.main.dashboard.Panel, {
    extend: Ext.dashboard.Dashboard,
    xtype: main_dashboard_panel,

    columnWidths: [
        0.5,
        0.5
    ]
});

/**
 * メインパネル。
 *
 * @class Sample.view.main.Panel
 * @extend Ext.panel.Panel
 */
Ext.define(Sample.view.main.Panel, {
    extend: Ext.panel.Panel,
    xtype: main_panel,

    requires: [
        Sample.view.main.dashboard.Panel,
        Sample.view.main.ViewController
    ],

    controller: main,

    cls: main-panel,

    layout: fit,

    dockedItems: {
        xtype: toolbar,
        items: [
            ->,
            {
                text: 列1に追加,
                handler: onClickAddColumn1Button
            },
            {
                text: 列2に追加,
                handler: onClickAddColumn2Button
            }
        ]
    },

    items: {
        reference: dashboard_panel,
        xtype: main_dashboard_panel
    }
});

/**
 * ビューコントローラクラス。
 *
 * @class Sample.view.main.ViewController
 * @extend Ext.app.ViewController
 */
Ext.define(Sample.view.main.ViewController, {
    extend: Ext.app.ViewController,
    alias: controller.main,

    /**
     * 列1に追加ボタンクリック時の処理。
     */
    onClickAddColumn1Button: function () {
        var me = this;
        
        // 第1,2引数は、応用を考えて仮の値を固定値で渡している。
        // 実際には、他の入力フィールドの値やサーバからのレスポンスデータを渡すことが考えられる。
        me.addComponent(me.getContentId(), panel, 0);
    },

    /**
     * 列2に追加ボタンクリック時の処理。
     */
    onClickAddColumn2Button: function () {
        var me = this;
        me.addComponent(me.getContentId(), panel, 1);
    },

    /**
     * コンポーネントを追加する。
     * 
     * @param {Number} id ID
     * @param {String} type ビューの種類
     * @param {Number} columnIndex 列インデックス番号
     */
    addComponent: function (id, type, columnIndex) {
        var me = this,
            dashboardPanel = me.lookupReference(dashboard_panel),
            partKey = me.getPartKey(id, type),
            parts = dashboardPanel.getParts();

        dashboardPanel.setParts(me.getPartConfig(id, type), parts);

        dashboardPanel.addNew(partKey, columnIndex);
    },

    /**
     * Ext.dashboard.Partのコンフィグを返す。
     * 
     * @param {Number} id ID
     * @param {String} type ビューの種類
     * @returns {Object} コンフィグ
     */
    getPartConfig: function (id, type) {
        var me = this,
            partKey = me.getPartKey(id, type),
            config = {};

        config[partKey] = {
            viewTemplate: {
                items: me.getPartItemConfig(id, type)
            }
        };

        return config;
    },

    /**
     * Ext.dashboard.Partに設定するアイテムコンポーネントのコンフィグを返す。
     * 
     * @param {Number} id ID
     * @param {String} type ビューの種類
     * @returns {Object} コンフィグ
     */
    getPartItemConfig: function (id, type) {
        // MEMO: 実案件などに使う場合は、おそらくtypeに応じて返すコンフィグを切り替えたりすることになる
        return {
            xtype: type,
            html: content  + id
        };
    },

    /**
     * partsコンフィグのキーを返す。
     * 
     * @param {Number} id ID
     * @param {String} type ビューの種類
     * @returns {String} キー
     */
    getPartKey: function (id, type) {
        return type + id;
    },

    /**
     * IDを生成する。
     * @returns {number} ID
     */
    getContentId: function () {
        return Math.floor(Math.random() * 100);
    }
});

少し応用などを考えた実装になっていますが、やりたかったことの実装部分はaddComponentメソッドです。

注意としては、Ext.dashboard.DashboardクラスのcolumnWidthsコンフィグを指定しておくことです。

columnWidthsコンフィグは列の幅の割合を、1を分け合う値で指定するのですが、これを指定していないとおかしな挙動になります。

 

 

 

ビューの削除やドロップのイベントについても取り上げようと思いましたが、Ext.dashboardパッケージのクラスのソースを見ればわかりそうなので今回は割愛です。