Celleditor для значения объекта Extjs4

Я ищу лучшее решение, как это сделать. Что я имею:

// model
Ext.define("User", {
    extend: "Ext.data.Model",
    fields: [
        {name: "id", type: "int"},
        {name: "name"},
        {name: "description", type: "string"}
    ]
});
// store with data
var oStore = new Ext.data.Store({
    model: "User",
    data: [
        {id: 1, name: {name:"John"}, description: "Fapfapfap"},
        {id: 2, name: {name:"Danny"}, description: "Boobooboo"},
        {id: 3, name: {name: "Tom"}, description: "Tralala"},
        {id: 4, name: {name:"Jane"}, description: "Ololo"},
    ]
});
// and finally I have a grid panel
Ext.create("Ext.grid.Panel", {
    columns: [
        {dataIndex: "id", header:"ID"},
        {
            dataIndex: "name", 
            header: "Name", 
            renderer: function(value){return value.name;}, 
            editor: "textfield"},
        {dataIndex: "description", header: "Description", flex: 1, editor: "htmleditor"}
    ],
    plugins: [new Ext.grid.plugin.CellEditing({clicksToEdit: 2})],
    store: store,
    renderTo: document.body
});​

Когда я дважды нажимаю на ячейку, я вижу [object] Object в поле редактора, а когда я ввожу действительное значение, я вижу пустую ячейку в сетке.

Итак, вопрос: как мне настроить celleditor, чтобы он получал данные не из record.name, а из record.name.name?


person balkon_smoke    schedule 22.02.2012    source источник


Ответы (3)


Вы можете переопределить методы get и set в модели, чтобы поддерживать многоуровневые имена полей. Ниже приведен пример реализации.

Ext.define("User", {
    extend: "Ext.data.Model",
    fields: [
        {name: "id", type: "int"},
        {name: "name"},
        {name: "description", type: "string"}
    ],
    get: function(key) {
        if (Ext.isString(key) && key.indexOf('.') !== -1) {
            var parts = key.split('.');
            var result = this.callParent([ parts[0] ]);
            return result[parts[1]];
        }
        return  this.callParent(arguments);
    },
    set: function(key, value) {
        if (Ext.isString(key) && key.indexOf('.') !== -1) {
            var parts = key.split('.');
            var result = this.get(parts[0]);
            result[parts[1]] = value;

            this.callParent([ parts[0], result ]);
            return;
        }
        this.callParent(arguments);
    }
});

Я не уверен, что магазин обнаруживает изменения, внесенные в поле name.name. Если нет, вам, вероятно, также следует пометить запись как грязную.

Рабочий образец: http://jsfiddle.net/lolo/dHhbR/2/.

person Krzysztof    schedule 22.02.2012
comment
Почему бы не использовать свойство сопоставления для глубокой ссылки на поле, например: {имя: имя, сопоставление: 'имя.имя'} - я делаю это повсюду. - person dbrin; 24.02.2012

Редактор принимает любое значение, указанное в поле «dataIndex» столбца. Поскольку «имя» — это объект, это то, что вы получаете. После ввода имени в редакторе значение равно строке (не объекту), и ваш рендерер пытается получить свойство имени строки.

Самый простой способ исправить это — сделать поле «имя» вашего магазина строкой, а не объектом. Однако я предполагаю, что есть причина, по которой вы хотите сделать это таким образом.

Плагин CellEditing имеет три события, которые он может прослушивать: beforeedit, edit и validateedit. Вы можете реализовать прослушиватель перед редактированием, чтобы получить объект «имя» из столбца, затем получить свойство «имя» этого объекта и заполнить редактор этим значением. Затем в validateedit получите значение из редактора и установите свойство «имя» объекта «имя» в записи с этим значением.

Для справки, вот определение события: События CellEditing

person Eric    schedule 22.02.2012
comment
+1 Я только начал печатать то же самое, я никогда не видел, чтобы этот новый ответ размещал ajax-штучку, которая всплывает в середине ответа - person egerardus; 22.02.2012
comment
да, я думал об этом, но я пытаюсь избежать лишних слушателей, лучшее решение для меня - модифицировать модель, поэтому я один раз меняю ее и буду счастлив в дальнейшем. - person balkon_smoke; 23.02.2012

Более простой способ - изменить объект модели пользователя, чтобы по-другому сопоставить свойство «имя»:

{name: "name", mapping:'name.name'}

тогда все остальное остается прежним.

person dbrin    schedule 23.02.2012
comment
Если я добавлю mapping: "name.name" к определению поля модели, когда я нажму для редактирования - редактор будет содержать значение <div unselectable="on" class="x-grid-cell-inner x-unselectable" style="text-align: left; " id="ext-gen1069">Tom</div> - person balkon_smoke; 23.02.2012
comment
Разве это не то, чего ты хочешь? Я что-то пропустил? - person dbrin; 24.02.2012
comment
Я хочу видеть только исходное значение в редакторе без какой-либо разметки Ext. - person balkon_smoke; 24.02.2012
comment
это должно работать, вы пробовали удалить ненужный рендерер? - person dbrin; 24.02.2012
comment
Данные в хранилище должны иметь правильный формат. Ваши данные представляют собой необработанный JSON и должны быть загружены с помощью loadRawData (см. jsfiddle.net/dbrin/HSVj8) чтобы воспользоваться преимуществами сопоставления полей модели. Если вы загружаете данные с сервера, просто store.load() сделает то же самое. - person dbrin; 27.02.2012