Резюме + пейджинг ajax на ExtJS.Grid

У меня есть сетка с данными, похожими на http://dev.sencha.com/deploy/ext-4.0.1/examples/grid/array-grid.html, но с использованием выгружаемого прокси-сервера, аналогичного http://dev.sencha.com/deploy/ext-4.0.1/examples/grid/paging.html.

Мне нужно добавить сводку, аналогичную http://dev.sencha.com/deploy/ext-4.0.1/examples/grid/group-summary-grid.html, только 1 внизу сетки. Он должен суммировать все данные, а не только данные с текущей страницы.

Я могу сделать запрос к БД, не нужно Ext для суммирования значений. Но как я буду отправлять сводные данные в Ext.store и из магазина в сетку?


person Hikari    schedule 04.09.2015    source источник
comment
Возможно, будет проще добавить в модель дополнительное поле, привязанное к хранилищу (например, сводку). Заполнить это поле из json и показать где-нибудь в сетке?   -  person Paweł Głowacz    schedule 04.09.2015
comment
Может быть, вы видели пример, который я мог бы использовать? Тем не менее, мне нужен визуальный эффект сводки ExtJs.Grid, это не может быть просто еще одна строка сетки.   -  person Hikari    schedule 08.09.2015
comment
@Hikari Вы всегда можете использовать свойство SummaryRenderer столбца, откуда вы можете возвращать пользовательские значения и применять форматирование.   -  person Avinash T.    schedule 14.09.2015


Ответы (3)


Относитесь к этому как к примеру, как вы могли бы реализовать.

Вот как это выглядит (конечно, это будут другие данные, но вы понимаете): < img src="https://i.stack.imgur.com/VVTsQ.png" alt="введите здесь описание изображения">

Давайте посмотрим на пример json (как это может быть и как я понимаю вашу проблему):

{
   "stats":[
      {
         "name":"Amount summary",
         "value":"2300"
      },
      {
         "name":"Mortgage",
         "value":"1100"
      }
   ],
   "success":true,
   "totalCount":2,
   "items":[
      {
         "Amount":"1000",
         "Delta":"3",
         "Mortgage":"500"
      },{
         "Amount":"1300",
         "Delta":"4",
         "Mortgage":"600"
      }
   ]
}

Модель:

Ext.define('Application.model.MyModel', {
    extend: 'Ext.data.Model',
    fields: [{
        name: 'Amount',
        type: 'string'
    },{
        name: 'Delta',
        type: 'string'
    },{
        name: 'Mortgage',
        type: 'string'
    }]
});

Магазин:

var writer = new Ext.data.JsonWriter({
    type: 'json',
    encode: false,
    listful: true,
    writeAllFields: true,
    returnJson: true
});

var reader = new Ext.data.JsonReader({
    type: 'json',
    totalProperty: 'totalCount',
    rootProperty: 'items',
    successProperty: 'success'
});

var proxy = new Ext.data.HttpProxy({
    reader: reader,
    writer: writer,
    type: 'ajax',
    url: 'urlForJson',
    headers: {
        'Content-Type': 'application/json; charset=UTF-8'
    }
});

Ext.define('Application.store.MyStore', {
    extend  : 'Ext.data.Store',
    storeId : 'MyStore',
    model   : 'Application.model.MyModel',
    autoLoad: false,
    autoSync: true,
    proxy:proxy
});

Давайте определим контроллер, который будет обрабатывать нашу сводку/статистику:

Ext.define('Application.controller.SummaryController', {
    extend: 'Ext.app.Controller',
    refs: [
        {
            selector: 'summaryPanel',
            ref: 'summaryPanel'
        }
    ],
    init: function () {
        var controller = this;
        controller.listen({
            controller: {
                '*': {
                    addSummary: 'addSummary'
                }
            }
        });
    },

    /**
     * Add summary.
     */
    addSummary: function addSummary(summary) {
        var controller = this;
        var summaryPanel= controller.getSummaryPanel();
        summaryPanel.removeAll();
        Ext.Object.each(stats, function(property, stat){
            var labelFieldName = new Ext.form.Label({
                text: stat.name+': '
            });
            var labelFieldValue = new Ext.form.Label({
                text: stat.value+'  ',
                cls: 'bold-item'
            });
            summaryPanel.items.add(labelFieldName);
            summaryPanel.items.add(labelFieldValue);
        });
        summaryPanel.up('window').doLayout();
    }
});

А это наша SummaryPanel:

Ext.define('Application.view.SummaryPanel', {
    extend: 'Ext.Panel',
    alias: 'widget.summaryPanel',
    xtype: 'summaryPanel',
    layout: 'anchor',
    bodyStyle: 'padding: 5px 5px;',
    items: []
});

На следующем шаге мы собираемся загрузить наши данные в сетку, а после этого мы заполним наш SummaryPanel статистикой/резюме:

Ext.define('Application.controller.GridController', {
    extend: 'Ext.app.Controller',
    init: function () {
        var controller = this;

        controller.control({
            'gridControlPanel': {
                'afterrender': function () {
                    controller.loadStore();
                }
            }
        })
    },
    loadStore: function () {
        var controller = this;
        var store = Ext.getStore('Application.store.MyStore');
        store.load({
            callback: function (records, operation, success) {
                var data = Ext.JSON.decode(operation._response.responseText);

                if (!Ext.isEmpty(data.stats)) {
                    //After loading data, make statistics.
                    controller.fireEvent('addSummary', data.stats);//This event is handled by SummaryController
                }
            }
        });
    }
});

И это UI, которое охватывает все вышеперечисленное:

Ext.define('Application.view.GridWindow', {
    extend: 'Ext.window.Window',
    alias: 'widget.gridWindow',
    xtype: 'gridWindow',
    addMode: false,
    autoShow: true,
    width: 1200,
    height: 700,
    resizable: true,
    layout: 'fit',
    items: [{
        xtype: 'grid',
        store: 'Application.store.MyStore',
        dockedItems: [{
            xtype: 'pagingtoolbar',
            dock: 'bottom',
            store: 'Application.store.MyStore',
            displayInfo: true
        }]
    }],
    dockedItems: [{
        xtype: 'summaryPanel'//This is our summary panel that will show your summarize.
    }]
});
person Paweł Głowacz    schedule 08.09.2015
comment
Интересно, спасибо за подробное описание. Но если этот код приведет к сетке, похожей на http://i.stack.imgur.com/VVTsQ.png, мой менеджер не примет его. Я не могу понять, что там написано, но, кажется, над сеткой есть сводка. Мне нужно, чтобы сводка выглядела как специальная строка, как в http://dev.sencha.com/deploy/ext-4.0.1/examples/grid/group-summary-grid.html. Мне просто не нужна группировка, и мне нужно, чтобы значения предоставлялись с сервера, а не вычислялись на стороне клиента Ext. Если бы я добавил сводку вне сетки, я бы просто добавил ее вне Ext как обычный HTML. - person Hikari; 08.09.2015
comment
Такого рода вопросы нетривиальны и, вероятно, не принесут правильных ответов. Это то, что должно быть очень хорошо реализовано и адаптировано к вашим потребностям. Я только что представил некоторое доказательство концепции, которую вы можете использовать в своей реализации. - person Paweł Głowacz; 08.09.2015
comment
Да, я согласен, мне нужно объединить несколько примеров в один. Я попробую ваш код, я сначала развертываю текущую версию на сервере. В основном мне нужно представление, подобное сводному примеру, без группировки и подачи сводных данных с сервера из-за пейджинга. - person Hikari; 08.09.2015
comment
Я понимаю, что view.getFeature('group').toggleSummaryRow(showSummary); заставляет Ext.Grid показывать сводку, и каждый столбец имеет свой атрибут summaryRenderer для форматирования сводного значения. В вашем примере "stats" в json имеет суммарное значение. А SummaryController.addSummary() берет значение статистики и добавляет его к сводке. Чего я не могу понять, так это того, как вы берете SummaryController и подключаете его к сетке. Мне не нужна панель инструментов для переключения отображения сводки, она мне просто нужна. - person Hikari; 08.09.2015
comment
Чтобы упростить: какой код заставляет Ext.Grid показывать сводку и какой код перехватывает json "stats", чтобы сводка отображала его значения. Я могу добавить "stats" в json, если я смогу это сделать, это сработает. - person Hikari; 08.09.2015
comment
controller.fireEvent('addSummary', data.stats); эта часть отправляет событие на контроллер SummaryController и динамически добавляет сводку на панель. Все о событиях и о том, как они работают. Во-вторых, refs в SummaryController. Когда я определил ref как summaryPanel, я могу сделать это в методе addSummary: var summaryPanel= controller.getSummaryPanel(); - это так называемый хук :) - person Paweł Głowacz; 08.09.2015
comment
lol У меня проблемы с пониманием вашего кода, но я продвигаюсь. Обычно я не использую контроллеры, я подключаю столбцы, сохраняю и пейджинг прямо в Ext.grid.Panel. - person Hikari; 09.09.2015
comment
Я до сих пор не понимаю, как вы подключаете Application.controller.GridController к Application.view.GridWindow и где подключается Application.controller.SummaryController. Мне не нужна Application.view.SummaryPanel, она не будет переключаться. Кроме того, просто чтобы было понятнее, я не буду использовать группировку, мне просто нужна сводка в нижней части сетки. - person Hikari; 09.09.2015
comment
Я использовал этот пример, немного изменив его, и заставил его работать с Infinite Grid с Ext JS 4.2.+- - person Matti Kiviharju; 10.05.2021

Вы можете использовать функцию ExtJS Grid —

Ext.grid.feature.Summary

для отображения сводки в нижней части сетки.

Вот простой пример ответа на ваш вопрос: https://fiddle.sencha.com/#fiddle/tq7

Например, я напрямую использовал объект summary в столбце summaryRenderer.

person Avinash T.    schedule 13.09.2015
comment
Я не думаю, что это отвечает на вопрос, относящийся к сетке с панелью инструментов подкачки. - person TimL; 21.09.2015

Итак, для итоговой строки у вас есть функция Summary. Вы можете вставить его в нижнюю часть сетки с помощью dock: 'bottom'. И, наконец, для использования удаленно вычисленных данных для сводки у вас есть remoteRoot. Вуаля.

... За исключением того, что эта вещь явно наполовину испечена и remoteRoot на самом деле используется только с группировкой. Упс. «Нет нужды заниматься простым случаем», — должно быть, подумали они.

Вот переопределение, которое заполняет недостающую часть, которая вам нужна (fiddle):

Ext.define('Ext.grid.feature.RemoteSummary', {
    override: 'Ext.grid.feature.Summary',

    // adds 'remote' summary type
    getSummary: function (store, type, field, group) {
        if (type === 'remote') {
            return this.getRemoteSummaryRecord(store).get(field);
        } else {
            return this.callParent(arguments);
        }
    },

    // helper for our custom summary type, mainly copied from:
    // http://docs.sencha.com/extjs/4.2.3/source/AbstractSummary.html#Ext-grid-feature-AbstractSummary-method-generateSummaryData
    getRemoteSummaryRecord: function(store) {
        if (!this.remoteSummaryRecord) {
            var reader = store.proxy.reader,
                remoteRoot = this.remoteRoot,
                root;

            if (remoteRoot && reader.rawData) {
                root = reader.root;
                reader.root = remoteRoot;
                reader.buildExtractors(true);

                this.remoteSummaryRecord = reader.read(reader.rawData).records[0];

                if (!reader.convertRecordData) {
                    reader.buildExtractors();
                }

                reader.root = root;
                reader.buildExtractors(true);
            }
        }
        if (!this.remoteSummaryRecord) {
            this.remoteSummaryRecord = store.model.create({});
        }
        return this.remoteSummaryRecord;
    },

    // ensure our remoteSummaryRecord stays fresh
    onStoreUpdate: function() {
        delete this.remoteSummaryRecord;
        return this.callParent(arguments);
    }
});

Затем вы должны использовать его следующим образом:

Ext.create('Ext.grid.Panel', {
    features: [{
        ftype: 'summary',
        remoteRoot: 'summary', // summary key in the server response
        dock: 'bottom'
    }],
    columns: [{
        text: 'Age',
        dataIndex: 'age',
        summaryType: 'remote'
    }]
    //...
});

С некоторыми данными такой формы:

{
    "summary": {
        "age": 95,
    },
    "items": [/*...*/]
}

(И, да, суммирование возрастов имеет большой смысл)

person rixo    schedule 14.09.2015
comment
Этот пример работает! - person Matti Kiviharju; 16.05.2021