dgrid внутри ContentPane - ошибка прокрутки

У меня проблема с dgrid... У меня есть AccordionContainer, и в каждой его ContentPane я помещаю dgrid. Проблемы с dgrid: 1- Ошибка со скроллом: при прокрутке вниз в определенный момент скролл "проскакивает" и прыгает в конец и нет возможности прокрутить вверх и показать первые записи. (Я видел в Firebug ошибку TypeError: grid._rows имеет значение null при сбое прокрутки). 2- Попытка изменить значение: похоже, что событие dgrid-datachange не генерируется, нет возможности зафиксировать событие после редактирования значения.

Я думаю, что эти ошибки связаны с наличием dgrid внутри макетов (dgrid внутри ContentPane, внутри AccordionContainer). Я также включил расширение DijitRegistry, но даже с этим расширением я не могу избавиться от этих ошибок. Я подготовил эту скрипку, которая воспроизводит ошибки:

https://jsfiddle.net/9ax3q9jw/5/

Код:

var grid = new (declare([OnDemandGrid, DijitRegistry,Selection, Selector, Editor]))({
            collection: tsStore,
            selectionMode: 'none',
            columns:
                [
                    {id: 'timestamp', label:'Timestamp', formatter: function (value,rowIndex) {
                        return value[0];
                    }},
                    {id: 'value', label: 'Value',
                        get: function(value){
                            return value[1];
                        },
                        editor: "dijit/form/TextBox"
                    }
                ],
            showHeader: true
        });
        grid.startup();
        grid.on('dgrid-datachange',function(event){
            alert('Change!');
           console.log('Change: ' + JSON.stringify(event));
        });

        //Add Grid and TextArea to AccordionContainer.
        var cp = new ContentPane({
            title: tsStore.name,
            content: grid
        },"accordionContainer");

Любая помощь будет оценена, Спасибо, Ангел.


person Ote    schedule 14.04.2015    source источник


Ответы (1)


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

Данные

Хранилище, используемое в скрипке, создается с массивом массивов, но хранилища предназначены для работы с массивами объектов. Это корень проблемы с прокруткой, которую вы видите. Одно свойство в каждом объекте должно однозначно идентифицировать этот объект (поле «id»). Без идентификаторов записей сетка не может должным образом отслеживать записи в вашем наборе данных. Массив данных можно легко преобразовать в массив объектов, где каждая запись имеет свойства timestamp и value, а хранилище может использовать timestamp в качестве своего свойства ID (свойство, которое используется для уникальной идентификации каждой записи).

var records = [];
var data = _globalData[0].data;
var item;
for (var i = 0; i < data.length; i++) {
    item = data[i];
    records.push({
        timestamp: item[0],
        value: item[1]
    });
}

var tsStore = new declare([Memory, Trackable])({
    data: records,
    idProperty: 'timestamp',
    name: 'Temperature'
});
_t._createTimeSeriesGrids(tsStore);

Такая настройка хранилища также позволяет упростить определения столбцов сетки. Использование имен полей вместо идентификаторов позволит сетке вызывать formatter функций с соответствующим значением поля для каждого объекта строки.

columns: [{
    field: 'timestamp',
    label: 'Timestamp',
    formatter: function (value) {
        return value;
    }
}, {
    field: 'value',
    label: 'Value',
    formatter: function (value) {
        return value;
    },
    editor: "dijit/form/TextBox"
}],

Загрузка

Скрипка использует декларативные виджеты и функцию автоматического синтаксического анализа Dojo для построения страницы. В этой ситуации обратный вызов загрузчика не ожидает завершения синтаксического анализатора перед выполнением, поэтому экземпляры виджетов могут не создаваться во время выполнения обратного вызова.

Есть два способа справиться с этим: dojo/ready или явное использование парсера.

parseOnLoad: true,
deps: [
    ...
    dojo/ready,
    dojo/domReady! 
],
callback: function (..., ready) {
    ready(function () {
        var _t = this;
        var _globalData = [];
        ...
    });
}

or

parseOnLoad: false,
deps: [
    ...
    dojo/parser,
    dojo/domReady! 
],
callback: function (..., parser) {
    parser.parse().then(function () {
        var _t = this;
        var _globalData = [];
        ...
    });
}

Макет

При добавлении виджетов в контейнеры используйте методы Dijit, такие как addChild и set('content', ...). Обычно они выполняют действия, отличные от простого добавления виджета в DOM, например запуск дочерних виджетов.

var cp = new ContentPane({
    title: tsStore.name,
    content: grid
});
registry.byId('accordionContainer').addChild(cp);

вместо

var cp = new ContentPane({
    title: tsStore.name,
    content: grid
}, "accordionContainer");

В примере кода ContentPane даже не нужен, так как dgrid наследуется от DijitRegistry — его можно добавить непосредственно как дочерний элемент AccordionContainer. Это также вызовет метод запуска сетки, поэтому явный вызов в коде не требуется.

registry.byId('accordionContainer').addChild(grid);

Также часто бывает необходимо переразметить контейнер сетки после того, как сетка была первоначально визуализирована, чтобы обеспечить ее правильный размер.

var handle = grid.on('dgrid-refresh-complete', function () {
    registry.byId('accordionContainer').resize();
    // only need to do this the first time
    handle.remove();
});
person jason0x43    schedule 14.04.2015
comment
Привет Джейсон, Спасибо за ваш ответ. Он отлично работает, добавляя идентификаторы в магазин. Теперь у меня нет проблем с прокруткой. Но теперь проблема с обновлением значений dgrid сохраняется... У меня нет возможности "отловить" событие обновления в dstore/dgrid... Я "прослушал" для grid.on('dgrid-datachange') и tsStore. on('update'), но похоже, что с плагином Editor событие не запускается .... есть подсказка? Заранее спасибо, - person Ote; 15.04.2015
comment
grid.on('dgrid-datachange') должно работать нормально (слушатель в вашем исходном примере отлично работает для меня). Обратите внимание, что он срабатывает только тогда, когда редактор теряет фокус, поэтому вам нужно щелкнуть или выйти из ввода, прежде чем событие сработает. - person jason0x43; 15.04.2015
comment
Чтобы запустить событие обновления магазина (для store.on('update', ...)), вам нужно включить autoSave для столбца редактора. Процесс редактирования сетки состоит из двух частей: обновление значений ячеек сетки и фактическое сохранение этих изменений в сетке. По умолчанию изменение значений обновляет только сетку, и вам нужно вызвать grid.save() самостоятельно. Установка для autoSave значения true в определении столбца приведет к тому, что сетка будет автоматически сохранять изменения в хранилище при изменении значения. - person jason0x43; 15.04.2015
comment
В скрипке и в реальном проекте «dgrid-datachange» у меня не работал. Но я нашел решение... Мне пришлось добавить свойство «поле» в определение столбца с помощью редактора, и теперь оно работает. Мне пришлось посмотреть код Editor.js, и он ожидает свойство column.field. - person Ote; 15.04.2015
comment
Насчет обновления магазина... да, пробовал со свойством автосохранения. Я пробовал с автосохранением и без него и grid.save() - person Ote; 15.04.2015