ExtJS 4 XTemplate 类关联

11

我正在测试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响应如下(仅显示“snapshot”节点):

    {
        "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"概念,因此我创建了快照(Snapshot)和模型(Model)的模型,并根据API文档创建了相关联的关系。

快照(Snapshot)模型:

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 ;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时没有显示我的任何模型,但如果我从Snapshot模型中删除关联,只添加另一个名为“models”的字段,它就可以正常工作。

在使用关联时正确显示模型列表的最佳实践是什么? 我需要使用嵌套模板和自定义函数来实现吗?

6个回答

7

好问题 (+1)

看起来在XTemplate中直接使用关联是不可能的(今天),因为XTemplate期望对象数组。 (当您拥有关联时,这不再是真的)

您有三个选项 -

  1. 摆脱像您提到的那样的关联。(听起来不太好,但可行)
  2. 如果您使用模板的数据视图,请覆盖Ext.view.AbstractView.prepareData并从您的模型创建对象数组
  3. 在调用apply之前,遍历snapshotStore.getRange()并(重新)生成带有“models”属性的对象,并将此数组传递给.apply

这有点自食其果,我确实喜欢Sencha中ORM的概念,大多数语言现在都有某种形式的ORM,我可以看到这个功能成为他们MVC概念的坚实基石,但是我真诚地希望它能够离线工作。也许下一个版本会带来这个功能。目前,我认为我会坚持使用模型概念而不带关联,因为这将是我项目最少痛苦的过渡模型。 - Greg
1
我同意。总的来说,ExtJS4有很多好的东西,但在质量方面却失败了惨不忍睹。(甚至文档也不完整,很多文章在解释某些内容时就中途停止了)看看Sencha论坛,“灯是亮着的,但没有人在家”。无论如何,如果这个答案对你有帮助,请考虑点赞或接受。 - Amol Katdare
1
值得注意的是,对于未来的浏览器,prepareData方法(截至4.1 beta2)现在确实使用getAssociatedData方法,并将其应用于返回的数据对象。 - Stuart

3

需要指出的是,从4.1版本开始,模型记录具有名为getData()的方法,如果使用getData(true)进行调用,则还将返回关联的数据。


那又有什么帮助呢? - oldwizard

2

我完全同意模板应该像这样。然而,通过关联,实际上很容易让模板做到你想要的事情。模型将所有字段存储在一个名为data的属性中,并使用约定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>'
);

试试这个替代方案'<tpl for="models"><p>{name} - {description}</p></tpl>', - Grgur

0
你可以在 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;
        }
    }
}

0

就像 @Izhaki 所说的那样,在记录上使用 getData(true) 将数据传递到模板,然后执行 @Aaron 所说的循环数据的变化。例如,如果模板是容器的一部分:

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

这个模板片段应该可以正常工作:

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

如果您使用商店(有多个模型),这将无法工作。 - oldwizard

-1
从我的最近经验来看,如果你不是通过存储库工作,就不应该有问题。 ExtJS 4文档中的XTemplate示例可以正常工作(至少对我来说是这样)。您可以为这些数据添加一个模型,然后示例将正常工作。
我尝试通过存储库做同样的事情。当您将store.first().data传递给overwrite(...) XTemplate方法时,关联不在该结构中。 您可以在以下代码中检查:
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)
}

你也可以尝试一下(看看XTemplate-Store-Associations有多糟糕)http://www.sencha.com/forum/showthread.php?127320-FIXED-EXTJSIV-242-multiple-HasMany-association-conflict-in-XTemplate

抱歉没有提供解决办法 :(

威利


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接