开发者

extjs 4 XTemplate class associations

I'm testing out extjs 4 and I have stumbled upon something, I can't seem to figure out.

I have simple object association: Snapshot - hasMany -> Model

Now, I am trying to use XTemplate to show this association in View component, so I have my XTemplate looking like this:

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>'
);

And my JSON response looks like this (showing just 'snapshot' 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"
            }
        ]
    }

As extjs 4 introduces concept of Model I have created models for Snapshot and Model and created association according to API docs.

Snapshot model:

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'
});

Model model ;P

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

And this is where my problem lies - When I use this setup, none of my models is displayed when XTemplate is being executed, however if I remove associations from Snapshot model and just add another field called 'models' it works OK.

What is the best practise to display list of models correctly while using associations? Would I have to use nested templates and custom functions to do th开发者_如何学JAVAis?


Good Question (+1)

It seems using the associations directly in the XTemplate is not possible (today) because XTemplate expects array of objects. (When you have associations, this is no longer true)

You have three options -

  1. Get rid of associations like you mentioned. (does not 'sound' good but will work)
  2. If you have a data view using the template, override Ext.view.AbstractView.prepareData and create array of objects from your models
  3. Before you call apply, iterate over the snapshotStore.getRange() and (re)generate objects with "models" attribute and pass this array to .apply


I should point out that as of 4.1, a model record has a method called getData(), which if called using getData( true ) will also return the associated data.


I totally agree it would be ideal to have templates look like this. However, it's actually quite easy to get a template to do what you want with associations. Models hold all of their fields within a property called data and associations at the root level with the convention: associationName+'Store'. Therefore, all you need to do is write your template as follows:

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>'
);


You can listen on the store.load event and add the associated data back to the store record, and then the template will work (I did this using the RowExpander's 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;
        }
    }
}


Like @Izhaki says use getData(true) on the record to pass the data to the template, then do a variation of what @Aaron says to loop thru the data. For example, if the template is part of a container:

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

This template snippet should work fine:

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


from my very recent experience, you shouldn't have problems if you are NOT working through stores. The XTemplate example from ExtJS 4 docs works ok (at least for me). You can add a model for those data and the example will be working on.

I tried to do the same through a store. When you pass the store.first().data to the overwrite(...) XTemplate method, the associations are not in that structure. You can check in the following code:

var data = {
    name : 'Tommy Maintz',
    title : 'Lead Developer',
    company : 'Sencha Inc.',
    email : 'tommy@sencha.com',
    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)
}

You can also can try (to see how bad XTemplate-Store-Associations work) at http://www.sencha.com/forum/showthread.php?127320-FIXED-EXTJSIV-242-multiple-HasMany-association-conflict-in-XTemplate.

sorry not to provide a solution : (

w i l l y

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜