【问题标题】:ExtJS: How to use itemSelector for XTemplate having nested loop?ExtJS:如何将 itemSelector 用于具有嵌套循环的 XTemplate?
【发布时间】:2014-07-21 11:21:21
【问题描述】:

我正在使用Ext.view.View 类创建一个数据视图,用于显示在 ajax 代理之后接收到的图像列表。根据 DataView 的 Sencha Doc,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 这样的类.. 所以它有点令人困惑我..有什么想法吗?

【问题讨论】:

    标签: javascript extjs ria extjs5


    【解决方案1】:

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

    您真正应该更改的唯一一件事是将total 添加到为模板提供的数据中。这比创建两个循环更容易。例如,您可以在 collectData 方法中这样做:

    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

    Worging 示例(无 css):http://jsfiddle.net/Xf7N8/6/

    【讨论】:

    • 谢谢@Lolo,但我不明白的一件事是,getTotalCount(); 是如何工作的?如果我从 json 中删除了 total 它的计数数组长度,否则它会获取属性 total.. !!和 2)。如果我在 json 响应中有多个数组,并且它们太复杂(例如另一个数组中的数组等)会发生什么。我是否必须为它们创建单独的模型?还是reader 可以动态获取所需的节点?
    • 你刚刚描述了getTotalCount 的工作原理:) 当你有服务器端分页时,你从服务器发送totalCount 所以JS 现在服务器端有多少页。如果您立即发送所有内容(没有服务器分页),那么您就不需要了。如果你想有更多的数组作为响应,那么你基本上需要扩展数据视图,因为它不支持开箱即用。很难说自定义视图来处理分层数据需要什么。事实证明,自定义树会更容易。
    • 那么如何访问其他属性.. 我的意思是例如startend 和 Xtemplate 中的其他可能属性?,对不起,如果这很烦人但理解这需要一点时间
    • collectData 中添加您需要的内容。返回的对象通过模板使用。您可以使用this.getStore().getProxy().getReader().rawData 访问startend 属性。
    • 太棒了... :) 太棒了!但为什么 ?我不能直接使用吗?就像我选择 rootProperty 作为数据然后迭代它的属性! ?
    【解决方案2】:

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

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

    有关此人的所有信息都应包含在 person div 中。

    【讨论】:

    • 我已经这样做了,但无济于事.. 如果你看到第二个 &lt;tpl for="images"&gt; 它是图像数组中的每条记录。我错过了什么吗?
    • 我上面说过,它需要映射到存储中的记录。您循环的商店位于外循环,而不是内循环。
    • ok.. 你的意思是说读者的rootProperty?请原谅我,因为我对 ExtJS 相关的东西还很陌生。
    • 没有。 &lt;tpl for="."&gt;&lt;/tpl&gt; 循环遍历商店中的每条记录。我认为您的数据定义是错误的。您的模型没有声明任何字段。从数据上看,rootProperty 应该是data.images
    猜你喜欢
    • 2012-01-27
    • 1970-01-01
    • 2021-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-25
    • 2014-10-28
    • 1970-01-01
    相关资源
    最近更新 更多