ExtJS:如何使用itemSelector的XTemplate嵌套循环

ExtJS: How to use itemSelector for XTemplate having nested loop?

本文关键字:XTemplate 嵌套循环 itemSelector 何使用 ExtJS      更新时间:2023-09-26

我正在Ext.view.View类上工作,以创建一个数据视图,用于显示ajax代理后收到的图像列表。根据Sencha Doc for DataView, itemSelector属性是必需的。所以我使用它作为itemSelector: 'div.thumb-wrap',但各自的类都在嵌套循环内,而不是在外部循环中,如下所示:
JS代码:

Ext.define("DSApp.Desktop.view.ImageView",{
extend: 'Ext.view.View',
alias : 'widget.imageviewer',
initComponent: function()
{
    Ext.apply(this,{
        itemId : 'image-data-view',
        autoScroll : true,
        width : 600,
        store : getDataStore(),
        tpl : ['<div id="carouselDiv">',
                '<tpl for=".">',               // 1st loop
                '<span>{total}</span>',
                '<a href="#" onclick="clickNext({#})">Prev</a>',
                '<tpl for="images">',          // 2nd loop
                    '<div class="thumb-wrap">', // itemSelector of my choice
                        '<div class="thumb"><img src="{src}" title="{caption}"></div>',
                        '<span class="x-editable">{caption:htmlEncode}</span>',
                    '</div>',
                '</tpl>',
                '<div class="x-clear"></div>',
                '<a href="#" onclick="clickNext({#})">Next</a>',
                '</tpl>',
                '</div>'],
        multiSelect : true,
        trackOver : true,
        overItemCls : 'x-item-over',
        itemSelector : 'div.thumb-wrap',  // its not working
        emptyText : 'No images to display',
        listeners : {
            afterrender : function(current, eOpts) {
                current.getStore().load();
            },
            containerclick : function(current, e ,opts)
            {
                console.log(current.ownerCt);
            }
        }           
    });
    this.callParent(arguments);
  }
});
function clickNext(index)
{
    Ext.Msg.alert("Alert","Just a dummy Alert");
}
JSON:

{
    data: {
      total: 120,
      start: 0,
      end: 20,
      images: [{...},{...},{...}]
    }
}  

存储:

Ext.define('ImageModel', {
    extend : 'Ext.data.Model',      
    proxy : {
        type : 'ajax',
        url: '/images',
        noCache : true,
        reader : {
            type : 'json',
            totalProperty: 'total',
            rootProperty : 'data'
        }
    }
});  
异常堆栈

:

Uncaught TypeError: Cannot read property 'internalId' of undefined ext-all.js:22
Ext.cmd.derive.updateIndexes ext-all.js:22
Ext.cmd.derive.refresh ext-all.js:22
Ext.cmd.derive.refresh ext-all.js:22
Ext.cmd.derive.refreshView ext-all.js:22
Ext.cmd.derive.onDataRefresh ext-all.js:22
Ext.cmd.derive.doFire ext-all.js:22
Ext.cmd.derive.fire ext-all.js:22
Ext.cmd.derive.doDispatchEvent ext-all.js:22
Ext.cmd.derive.dispatchEvent ext-all.js:22
Ext.cmd.derive.doFireEvent ext-all.js:22
a.doFireEvent ext-all.js:22
Ext.cmd.derive.fireEvent ext-all.js:22
Ext.cmd.derive.loadRecords ext-all.js:22
Ext.cmd.derive.onProxyLoad ext-all.js:22
Ext.cmd.derive.triggerCallbacks ext-all.js:22
Ext.cmd.derive.setCompleted ext-all.js:22
Ext.cmd.derive.setSuccessful ext-all.js:22
Ext.cmd.derive.process ext-all.js:22
Ext.cmd.derive.processResponse ext-all.js:22
(anonymous function) ext-all.js:22
Ext.apply.callback ext-all.js:22
Ext.cmd.derive.onComplete ext-all.js:22
Ext.cmd.derive.onStateChange ext-all.js:22
(anonymous function) ext-all.js:22  

每当我尝试使用itemSelector: 'div.blabla'时,它只是在控制台中没有任何问题。事实上,它不工作,因为没有类blabla。所以这对我来说有点令人困惑……你知道吗?

我觉得你做得太过分了。你不需要2个循环,因为你只从服务器返回一个图像数组。那么这有什么意义呢?

您实际上应该更改的唯一事情是将total添加到为模板提供的数据中。这比创建两个循环要容易得多。你可以这样做,例如在collectData method:

collectData: function(records, startIndex){
    var data = this.callParent(arguments);
    data.total = this.getStore().getTotalCount()
    return data;
}

然后你的模板看起来像这样:

tpl : [
    '<div id="carouselDiv">',
       '<span>{total}</span>',
       '<a href="#" onclick="clickNext({#})">Prev</a>',
       '<tpl for=".">',               // 1st loop
           '<div class="thumb-wrap">', // itemSelector of my choice
               '<div class="thumb"><img src="{src}" title="{caption}"></div>',
               '<span class="x-editable">{caption:htmlEncode}</span>',
           '</div>',
       '</tpl>',
       '<div class="x-clear"></div>',
       '<a href="#" onclick="clickNext({#})">Next</a>',
    '</div>'
]

你也应该把rootProperty改成images

工作示例(不含css): http://jsfiddle.net/Xf7N8/6/

itemSelector的作用是将DOM节点映射到存储中的记录。这意味着,您在itemSelector内包装的内容应该封装单个记录:

itemSelector: '.person',
tpl: [
    'some markup',
    '<tpl for=".">,
        '<div class="person">{name}</div>',
    '</tpl>'
],

关于人物的一切都应该在persondiv内。