初心者のためのExtJS入門

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

グリッドの機能:グルーピング・サマリー[classic]

グリッドのグルーピングとサマリーの機能を試します。

今回は注文一覧を会社ごとにグルーピングし、売上金額の小計を表示させます。

モデルとストア

そのため、↓のようなモデル、ストアを用意しました。

/**
 * 注文モデルクラス。
 *
 * @class Sample.model.Order
 * @extend Ext.data.Model
 */
Ext.define('Sample.model.Order', {
    extend: 'Ext.data.Model',

    fields: [
        {
            // ID
            name: 'id',
            type: 'int'
        },
        {
            // 商品名
            name: 'name',
            type: 'string'
        },
        {
            // 会社
            name: 'company',
            type: 'string'
        },
        {
            // 金額(単価)
            name: 'price',
            type: 'int'
        },
        {
            // 数量
            name: 'num',
            type: 'int'
        },
        {
            // 売上金額
            name: 'total',
            convert: function (value, record) {
                return record.get('price') * record.get('num');
            },
            depends: [
                'price',
                'num'
            ]
        },
        {
            // 作成日時(注文日時)
            name: 'created',
            type: 'date',
            dateFormat: 'Y/m/d H:i:s'
        }
    ]

});

/**
 * 注文ストアクラス。
 *
 * @class Sample.store.Order
 * @extend Ext.data.Store
 */
Ext.define('Sample.store.Order', {
    extend: 'Ext.data.Store',
    alias: 'store.order',

    requires: [
        'Ext.data.proxy.LocalStorage',
        'Sample.model.Order'
    ],

    model: 'Sample.model.Order',

    proxy: {
        type: 'localstorage',
        id: 'order'
    }
});

モデルのフィールドにconvertを使っています。これは他のフィールドを使って、新しくフィールドを定義する場合に使います。今回は「注文の小計」を表すフィールドを「単価 × 数量」として定義しました。

あとdependsには、convertで参照しているフィールド名を設定しておきます。dependsを設定しておくと、参照しているフィールドの値が変化したときに自動的に値を変更してくれるようになります。今回はあまり役に立ちませんが、dependsは設定しておいたほうが良いです。

ビュー

グルーピングとサマリーは、Ext.grid.feature.GroupingSummaryを使います。(Ext.grid.feature.Grouping、Ext.grid.feature.Summaryというクラスもあり、GroupingとSummaryをまとめたのがGroupingSummaryです)

featureのクラスは、featuresコンフィグにftype: (エイリアス名)と指定します。

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

    requires: [
        'Ext.grid.feature.GroupingSummary'
    ],

    title: '注文一覧',

    store: {
        type: 'order',
        autoLoad: true,
        groupField: 'company'
    },

    features: [
        {
            ftype: 'groupingsummary',
            groupHeaderTpl: '会社: {name}'
        }
    ],

    columns: [
        {
            dataIndex: 'created',
            text: '注文日時',
            xtype: 'datecolumn',
            format: 'Y/m/d H:i',
            width: 150
        },
        {
            dataIndex: 'name',
            text: '商品名',
            width: 300
        },
        {
            dataIndex: 'total',
            text: '売上金額',
            width: 200,
            align: 'right',
            renderer: function (value) {
                return Ext.util.Format.currency(value, '円', 0, true);
            },
            summaryType: 'sum',
            summaryRenderer: function(value){
                return '小計: ' + Ext.util.Format.currency(value, '円', 0, true);
            }
        }
    ]
});

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

グルーピングは、storeコンフィグのgroupFieldで指定しています。今回は会社ごとにグルーピングしたいので、groupField: 'company'としました。

サマリーは集計したいカラムにsummaryTypeとsummaryRendererを指定します(summaryRendererは任意)。summaryTypeには集計方法として、count、sum、min、max、averageが指定できます。summaryRendererは集計結果をどのように出力するかを関数で定義します。

groupHeaderTplでグルーピングした見出しのテキストを設定できます。

補足

今回はstoreの指定をオブジェクトリテラルにしました。

これまではstore: '(ストアID)'で指定していました。これはグローバルなストアを指定するという意味です。Application.jsでstoresにストアを設定すると、自動的にアプリケーション全体でグローバルなストアが1つ作成されます。その自動的に作成されたストアを使うよ、としていたわけです。

storeの指定をオブジェクトリテラルにしてtypeにストアのエイリアス名を指定すると、ストアのインスタンスを新しく作成して、それを使ってくれます。これはグローバルなストアとは全く別物です。今回はautoLoadとgroupFieldを設定したかったので、このようにしました。

 

 

 

ちなみにデータ投入は、画面を開いてからDeveloper Toolsのコンソールなどから↓のように直接実行すれば楽です(グローバルなストアを参照してるので、Application.jsのstoresにOrderストアを設定しといてくださいね)。

Ext.getStore('Order').add(
  { name: 'Tシャツ', company: '株式会社ABC', price: 1000, num: 2, created: new Date() },
  { name: 'パーカー', company: '株式会社ABC', price: 5000, num: 1, created: new Date() },
  { name: 'コート', company: '株式会社ABC', price: 12000, num: 1, created: new Date() },
  { name: 'バスタオル', company: '株式会社XYZ', price: 2000, num: 1, created: new Date() },
  { name: 'フェイスタオル', company: '株式会社XYZ', price: 500, num: 5, created: new Date() }
);
Ext.getStore('Order').sync();