Search code examples
javascriptextjsriaextjs5

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


I am working on Ext.view.View class to create one data view for displaying list of images received after ajax proxy. As per Sencha Doc for DataView, itemSelector property is mandatory. So I am using it as itemSelector: 'div.thumb-wrap' but respective class is inside the nested loop not in the outer loop as below:
JS code:

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: [{...},{...},{...}]
    }
}  

Store:

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

StackTrace:

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  

Whenever I am trying with itemSelector: 'div.blabla' its just go ahead without any problem in console.. indeed it do not work since there is no class as blabla.. so its kind of confusing stuff for me.. any idea ?


Solution

  • IMO you overdone that. You don't need 2 loops, because you return only one image array from server. So what is the point of that?

    Only thing you should actually change is to add total to data provided for template. It is easier than creating two loops. You can do that for example in collectData method:

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

    Then your template can look like this:

    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>'
    ]
    

    Also you should correct rootProperty and change it to images.

    Worging sample (without css): http://jsfiddle.net/Xf7N8/6/