【问题标题】:Add onLoad Listener to Sencha Touch List将 onLoad 监听器添加到 Sencha 触摸列表
【发布时间】:2014-02-10 12:56:56
【问题描述】:

我想在 List 加载数据后执行选择操作,因为根据我收到的数据我必须选择该列表中的一个单元格,还需要在此基础上更新详细视图。

    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

在这个实际视图的上方,我用来显示列表。我的问题是我尝试了onLoad() 方法它可以工作,但我想在我的控制器中做所有事情以使其更清晰。

如您所见,我的itemTap 事件已在控制器中通过触发事件进行处理。但同样不适用于load 事件。

【问题讨论】:

    标签: javascript extjs sencha-touch sencha-touch-2 sencha-touch-2.1


    【解决方案1】:

    正如@Jimmy 提到的,列表中没有onLoad 方法。但是,有几种方法可以解决它。我对您要实现的目标的理解是,当加载支持列表的商店时,您希望从 ProductList 实例(而不是 list)中触发一个事件,以便在控制器中您可以将 control 配置为是:

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

    如果是这样,那么我们可以修改您现有 ProductList 类中的侦听器以执行以下操作:

    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);
                }
            }
        }
    ]
    

    它的作用是显示列表然后获取它的存储,如果存储已加载则调用处理程序,否则直接在其上注册load 侦听器。请注意,这里的 this 对象将是 ProductList 而不是 product-list-view

    【讨论】:

    • 此解决方案不起作用,因为商店设置为 autoload:true 并且商店仅在用户点击主屏幕时才推送到屏幕。所以商店在列表初始化之前就已经加载了
    • @CoolMonster 我已将上面的内容更新为使用“show”,并检查商店是否已加载。希望这更符合您的要求
    • 谢谢。这就是我到目前为止所做的。但我想知道有没有其他方法可以做到这一点..
    • Dataview 类中存在 onLoad() 方法,但它是私有方法,并且该方法本身默认实现对列表的 unmask() 调用。
    【解决方案2】:

    根据 Sencha Touch 文档,我没有看到 Ext.dataview.ListonLoad 函数。但是,列表包含Ext.data.Storeload 事件侦听器。因此,您的事件侦听器可能应该在数据存储上,而不一定是列表本身。

    在控制器的启动方法中,您可以为 Store 的加载事件设置监听器,如下所示:

    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
    }
    

    您还应该在控制器中为您的列表设置事件侦听器。您无需在视图配置中创建侦听器,只需在 Controller 中调用 fireEvent 方法即可。相反,在控制器中进行所有事件处理。要在 Controller 中处理您的列表,请在 Ext.define 中为您的 WaxiApp.view.ProductViews.ProductList 添加一个 xtype: 'productlist'。然后,将您的列表作为参考添加到控制器的配置中,并为控件中的列表附加itemtap 事件,如下所示:

    config: {
        ref: {
            productList: 'productlist'
        },
    
        control: {
            productList: {
                itemtap: 'productListSelectCommand'
            }
        }
    },
    
    productListSelectCommand: function (list, index, target, record, e, eOpts) {
        // do some itemtap functionality
    }
    

    最后,你的控制器可能看起来像这样:

    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
        }
    }
    

    最后,不要忘记在Ext.define 中为您的WaxiApp.view.ProductViews.ProductList 添加xtype: 'productlist'。我不确定您对 Sencha Touch 应用程序设计的整体体验,但here 是了解他们的视图、模型、存储、控制器结构的一个很好的参考。

    【讨论】:

    • 提供您的方法可能有效,但有问题。使用这种方法是当视图被销毁并且重新创建控制器将不会处理通过控制器分配的 itemtap 事件。我还找到了一种方法来使用列表组件的 onLoad() 方法 来完成我的任务。
    【解决方案3】:

    我找到了如何处理这种情况的解决方案并发布了我的 自己的解决方案。

    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
    

    【讨论】:

      猜你喜欢
      • 2016-11-12
      • 1970-01-01
      • 1970-01-01
      • 2014-05-18
      • 1970-01-01
      • 2013-11-28
      • 1970-01-01
      • 2014-07-08
      • 1970-01-01
      相关资源
      最近更新 更多