Extjs 4 Ассоциации классов XTemplate

Я тестирую extjs 4, и я наткнулся на что-то, я не могу понять.

У меня есть простая ассоциация объектов: Снимок - hasMany → Модель

Теперь я пытаюсь использовать XTemplate для отображения этой ассоциации в компоненте View, поэтому у меня есть XTemplate, выглядящий так:

Ext.create('Ext.XTemplate',
'<tpl for=".">',
'<div class="snapshot" id="{id}">',
'<h1>{snapshot}</h1>',
'<p><span class="label">Created: </span>{dateString}</p>',
'<p><span class="label">Models</span></p>',
'<tpl for="models">',
'<p>{name}  - {description}</p>',
'</tpl>',
'</div>',
'</tpl>',
'<div class="x-clear bottompad"></div>'
);

И мой ответ JSON выглядит так (показывает только "моментальный снимок" node):

    {
        "id": 1,
        "snapshot": "Snapshot 1",
        "created": 1305806847000,
        "models": [
            {
                "id": 1,
                "name": "ABC",
                "description": "A B C"
            }, {

                "id": 111,
                "name": "ABCDD",
                "description": "A B C XCXC"
            }
        ]
    }

Как extjs 4 вводит концепцию Model I, я создал модели для Snapshot and Model и создал ассоциацию в соответствии с документами API.

Модель снимка:

Ext.define('Snapshot', {
    extend: 'Ext.data.Model',
    fields: [
        {name: 'id', type: 'int'},
        'snapshot',
        {name: 'created',type: 'date', dateFormat: 'time' }

    ],
    associations:[
      {type: 'hasMany', model: 'Model', name: 'models'}  
    ],
    idProperty: 'id'
});

Модель модели; P

Ext.define('Model', {
    extend: 'Ext.data.Model',
    belongsTo: 'Snapshot',
    fields: [
        { name: 'id',  type: 'int' },
        { name: 'snapshot_id', type: 'int' },            
        'name',
        'description'
    ],
    idProperty: 'id'
});

И вот здесь моя проблема. Когда я использую эту настройку, ни одна из моих моделей не отображается при выполнении XTemplate, однако, если я удалю ассоциации из модели моментальных снимков и просто добавлю другое поле под названием "модели", оно работает нормально.

Какова наилучшая практика отображения списка моделей при использовании ассоциаций? Должен ли я использовать вложенные шаблоны и настраиваемые функции для этого?

Ответ 1

Хороший вопрос (+1)

Кажется, использование ассоциаций непосредственно в XTemplate невозможно (сегодня), потому что XTemplate ожидает массив объектов. (Когда у вас есть ассоциации, это уже не так)

У вас есть три варианта -

  • Избавьтесь от таких ассоциаций, как вы упоминается. (не "звучит" хорошо но будет работать)
  • Если у вас есть представление данных с использованием шаблона, переопределите Ext.view.AbstractView.prepareData и создайте массив объектов из ваших моделей
  • Прежде чем вы назовете применить, выполните итерацию по snapshotStore.getRange() и (re) сгенерируйте объекты с атрибутом "models" и передайте этот массив в .apply

Ответ 2

Следует отметить, что с 4.1 модельная запись имеет метод под названием getData(), который, если вызываемый с помощью getData( true ) также возвращает связанные данные.

Ответ 3

Я полностью согласен, что было бы идеально, если бы шаблоны выглядели так. Однако на самом деле довольно легко получить шаблон, чтобы делать то, что вы хотите, с ассоциациями. Модели содержат все свои поля внутри свойства, называемого данными и ассоциациями на корневом уровне, с помощью соглашения: associationName + 'Store'. Поэтому все, что вам нужно сделать, это написать свой шаблон следующим образом:

var template = Ext.create('Ext.XTemplate',
    '<tpl for=".">',
        '<div class="snapshot" id="{data.id}">',
            '<h1>{data.snapshot}</h1>',
            '<p><span class="label">Created: </span>{data.created}</p>',
            '<p><span class="label">Models</span></p>',
            '<tpl for="modelsStore">',
                '<p>{data.name}  - {data.description}</p>',
            '</tpl>',
        '</div>',
    '</tpl>',
    '<div class="x-clear bottompad"></div>'
);

Ответ 4

Вы можете прослушивать событие store.load и добавлять связанные данные обратно в запись хранилища, а затем шаблон будет работать (я сделал это с помощью строки RowExpander rowBodyTpl).

listeners: {
    load: function(store,storeRecs) {
        var i,r;
        for (i=0;i<storeRecs.length;i++) {
            r = storeRecs[i];
            r.data.subItem = r.getAssociatedData().subItem;
        }
    }
}

Ответ 5

Как и @Izhaki говорит использовать getData (true) в записи для передачи данных в шаблон, а затем сделать вариацию того, что @Aaron говорит, чтобы пройти через данные. Например, если шаблон является частью контейнера:

 //...
 tpl: //your tpl
 data: record.getData(true)
 //....

Этот фрагмент шаблона должен работать нормально:

 '<tpl for="models">',
 '<p>{name}  - {description}</p>',
 '</tpl>'

Ответ 6

из моего недавнего опыта, у вас не должно быть проблем, если вы НЕ работаете через магазины. Пример XTemplate из документов ExtJS 4 работает нормально (по крайней мере для меня). Вы можете добавить модель для этих данных, и пример будет работать.

Я пытался сделать то же самое через магазин. Когда вы передаете данные store.first() в метод перезаписи (...) XTemplate, ассоциации не входят в эту структуру. Вы можете проверить следующий код:

var data = {
    name : 'Tommy Maintz',
    title : 'Lead Developer',
    company : 'Sencha Inc.',
    email : '[email protected]',
    address : '5 Cups Drive',
    city : 'Palo Alto',
    state : 'CA',
    zip : '44102',
    drinks : ['Coffee', 'Soda', 'Water'],
    kids : [{
                name : 'Joshua',
                age : 3
            }, {
                name : 'Matthew',
                age : 2
            }, {
                name : 'Solomon',
                age : 0
            }]
};



var kidsModelProps = {
    extend: "Ext.data.Model",
    fields: [
        "name",
        {name: "age", type: "int"}
    ]
}
Ext.define ("KidsModel", kidsModelProps)

var datamodelProps = {
    extend: "Ext.data.Model",
    fields: [
        "name", "title", "company", "email", "address",
        "city", "state", "zip", "drinks"
    ],

    hasMany: {name: "thekids", model: "KidsModel"},

    proxy: {
        type: "memory",
        reader: {
            type: "json"
        }
    }
}
Ext.define ("DataModel", datamodelProps)


var kidsStore = new Ext.data.Store({
    data: data,
    storeId: "kidsStore",
    model: "DataModel"

})

var tpl = new Ext.XTemplate(
    '<p>Name: {name}</p>',
    '<p>Title: {title}</p>',
    '<p>Company: {company}</p>',
    '<p>Kids: ',
    '<tpl for="kids">',     // interrogate the kids property within the data
        '<p>{name}</p>',
    '</tpl></p>'
);

Ext.onReady(function () {
    var thePanel = Ext.create ("Ext.panel.Panel", {
        html: "<b>Viewport tpl-test: build with separated files</b>",
        border: 10,
        height: 500,
        layout: {
            type: 'vbox',
            align: 'center'
        },
        renderTo: Ext.getBody(),
        bodyStyle: "background-color: yellow",

        items: []

    })
    var someData = kidsStore.first().data
    tpl.overwrite (thePanel.body, someData)
}

Вы также можете попробовать (посмотреть, как работают плохие ассоциации XTemplate-Store) в http://www.sencha.com/forum/showthread.php?127320-FIXED-EXTJSIV-242-multiple-HasMany-association-conflict-in-XTemplate.

жаль, что не предоставил решение: (

w я l l y