Question

I want to perform selection operation on List after the data has been loaded, because based on the data which I received I have to select one cell in that list and also need to update the detail view base on that.

    Ext.define('WaxiApp.view.ProductViews.ProductList', {
    extend: 'Ext.Container',
    alias: "widget.ProductList",
    requires: [
                   'Ext.Img',
    ],
    config: {
        layout: Ext.os.deviceType == 'Phone' ? 'fit' : {
            type: 'hbox',
            pack:'strech'
        },
        cls: 'product-list',
        items: [{
            xtype: 'list',
            id:'product-list-view',
            width: '100%',
            height:'100%',
            store: 'ProductsList',
            infinite: true,
            plugins: 'sortablelist',
            itemCls: 'productList',
            itemId:"product-item",
            itemTpl: new Ext.XTemplate(
                '<div class="list-content-div ',
      '<tpl if="this.needSortable(isNeedInventry)">',
            Ext.baseCSSPrefix + 'list-sortablehandle',

        '</tpl>',
         '">',
         '<b>{UpcCode} {Name}</b>',
        '<tpl if="isActive">',
            '</div>',
        '</tpl>',
            {
                // XTemplate configuration:
                compiled: true,
                // member functions:
                needSortable: function (isneedInventry) {
                    return !isneedInventry;
                },
            }),
            masked: { xtype: 'loadmask',message: 'loading' },
            onLoad: function (store) {
                this.unmask();
                console.log('list loaded');
                this.fireEvent("productListLoadedCommand", this,store);
            },

        }
        ],
        listeners: [
                {
                    delegate: "#product-list-view",
                    event: "itemtap",
                    fn: function (list, index, target, record) {
                        console.log(index);
                        console.log('list selection command fired');
                        this.fireEvent("productListSelectedCommand", this,index,record);
                    }
                }

        ],
        style: 'background-image: -webkit-gradient(linear, left top, right bottom, color-stop(0, #FDFDFD), color-stop(1, #DBDBDB));background-image: linear-gradient(to bottom right, #FDFDFD 0%, #DBDBDB 100%);'
    }//End of config

});//End of Define

Above this actual view I used to display the list. My problem is I tried onLoad() method it work but i want do everything in my Controller to make it more clear.

As you saw my itemTap event has been handled in Controller by firing event. But same is not working for load event.

Was it helpful?

Solution 3

I found the solution exactly how to handle this scenario and posted my own solution.

ProductList.js

Ext.define('WaxiApp.view.ProductViews.ProductList', {
extend: 'Ext.Container',
alias: "widget.ProductList",
requires: [
               'Ext.Img',
],
initialize: function () {

    this.add([
        {
            xtype: 'list',
            id: 'product-list-view',
            store: 'ProductsList',
            masked: { xtype: 'loadmask', message: 'loading' },
            //onLoad is not a listener it's private sencha touch method used to unmask the screen after the store loaded
            onLoad: function (store) {
                this.unmask();//I manually unmask, because I override this method to do additional task.
                console.log('list loaded');
                this.fireEvent("productListLoadedCommand", this, store);
            }
            ,
            //Painted is event so added it to listener, I saw fee document state that, add event like Painted and show should to added to the
            //Component itslef is best practice. 
            listeners: {
                order: 'after',
                painted: function () {
                    console.log("Painted Event");
                    this.fireEvent("ProductListPaintedCommand", this);
                },
                scope: this
                 //This is also very important, because if we using this in card layout
                 //and changing the active view in layout cause this event to failed, so
                 //setting scope to this will help to receive the defined view instead of this list component.
            }

        }]);
},

config: {
    listeners: [
            {
                delegate: "#product-list-view",
                event: "itemtap",
                fn: function (list, index, target, record) {
                    console.log(index);
                    console.log('list selection command fired');
                    this.fireEvent("productListSelectedCommand", this, index, record);
                }
            }
    ],

    }//End of config

});//End of Define

ProductViewController.js

/// <reference path="../../touch/sencha-touch-all-debug.js" />


Ext.define("WaxiApp.controller.ProductsViewController", {

    extend: "Ext.app.Controller",
    listStoreNeedLoad:true,
    config: {
        refs: {
            ProductContainer: "ProductList",
            ProductList: "#product-list-view",
            ProductDetailView:"ProductDetail"
        },
        control: {
            ProductContainer:{
                productListSelectedCommand: "onProductListSelected",
                ProductListPaintedCommand: "onProductListPainted"
            },
            ProductList:{
                productListLoadedCommand: "onProductListLoaded"        
            }

        }//End of control

    },//End of config
    // Transitions
    getstore:function(){
        return Ext.ComponentQuery.query('#product-list-view')[0].getStore();
    },
    onProductListPainted:function(list)
    {
        //Check for if need to load store because painted event called every time your view is painted on screen
        if (this.listStoreNeedLoad) {
            var store = this.getstore();
            this.getstore().load();
        }
    },
    onProductListLoaded:function(list,store)
    {
        this.listStoreNeedLoad = false;
        var index = 0;
        //Iterate through record and set my select Index
        store.each(function(record,recordid){
            console.info(record.get("isNeedInventry"));
            if (record.get("isNeedInventry")) {
                return false;
            }
            index++;
        });

        console.log('list load event fired');
        if(Ext.os.deviceType.toLowerCase()!='phone')
        {
            this.setRecord(store.getAt(index));
            list.select(index);
        }

    }

})//End of define

OTHER TIPS

As mentioned by @Jimmy there is no onLoad method on list. However there are a few ways to work around it. My understanding of what you want to achieve is that when the store backing the list is loaded, you want an event to be fired from the ProductList instance (not the list) such that in the controller you can configure the control to be:

control: {
    ProductList: {
        productListSelectedCommand: 'productListSelectCommand',
        productListLoadedCommand: 'productListLoadedCommand'
    }
}

If so then we can modify the listeners in your existing ProductList class to do the following:

listeners: [
    {
        delegate: "#product-list-view",
        event: "itemtap",
        fn: function (list, index, target, record) {
            console.log(index);
            console.log('list selection command fired');
            this.fireEvent("productListSelectedCommand", this,index,record);
        }
    },
    {
        delegate: "#product-list-view",
        event: "show",
        fn: function (list) {
            var store = list.getStore();
            var handler = function() {
                list.unmask();
                console.log('list loaded');
                this.fireEvent("productListLoadedCommand", this, store);
            };
            if (store.isLoaded()) {
                handler.apply(this)
            } else {
                list.getStore().on('load', handler, this);
            }
        }
    }
]

What this is does is to what for the list to be shown and then get it's store, if the store has loaded then invoke the handler, otherwise register a load listener directly on it. Note that the this object here will be the ProductList not the product-list-view.

Per the Sencha Touch documentation, I do not see an onLoad function for Ext.dataview.List. However, there is a load event listener for the Ext.data.Store, which the list contains. So, your event listener should probably be on the data store, not necessarily the list itself.

Inside your controller's launch method, you could setup a listener for the Store's load event like so:

launch: function () {        
    // your store should be setup in your Ext.application
    Ext.getStore('NameOfStore').on('load', this.productListLoadedCommand);
},

productListLoadedCommand: function(store, records, successful, operation, eOpts) {
     // do some after load logic
}

You should set up your event listener for your list in the controller as well. There should be no need for you to create a listener in the view config only to call a fireEvent method in the Controller. Instead, do all event handling in the controller. To get a handle on your list in the Controller, add a xtype: 'productlist' inside the Ext.define for your WaxiApp.view.ProductViews.ProductList. Then, add your list to the Controller's config as a ref and attach the itemtap event for the list in the control like so:

config: {
    ref: {
        productList: 'productlist'
    },

    control: {
        productList: {
            itemtap: 'productListSelectCommand'
        }
    }
},

productListSelectCommand: function (list, index, target, record, e, eOpts) {
    // do some itemtap functionality
}

In the end, your controller might look something like this:

Ext.define('MyApp.controller.Controller', {
    extend: 'Ext.app.Controller',

    requires: [
        // what is required
    ],

    config: {
        ref: {
            productList: 'productlist'
        },

        control: {
            productList: {
                itemtap: 'productListSelectCommand'
            }
        }
    },

    launch: function () {        
        // your store should be setup in your Ext.application
        Ext.getStore('NameOfStore').on('load', this.productListLoadedCommand);
    },

    productListLoadedCommand: function(store, records, successful, operation, eOpts) {
         // do some after load logic
         // this.getProductList() will give you handle of productlist
    },

    productListSelectCommand: function (list, index, target, record, e, eOpts) {
        // do some itemtap functionality
    }
}

Finally, don't forget to add a xtype: 'productlist' inside the Ext.define for your WaxiApp.view.ProductViews.ProductList. I'm not sure of your overall experience with Sencha Touch application design, but here is a good reference for understanding their view, model, store, controller structure.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top