Sencha Touch 2:使用多个存储填充一个DataView

3
我知道这可能听起来很傻,希望这不会让人觉得太蠢。我想要使用多个商店来填充一个数据视图或其他可以应用 itemTpl 的项目。 我有一个基本的想法要实现:
  • 我有一组用户和物品,用户可以购买物品。
  • 每个用户都有一个关联余额,它决定了他们可以购买哪些物品。
我想要呈现一个可以购买的物品列表(无论用户是否有足够的钱在账户中)。任何用户买不起的物品应该被变灰掉(但仍然可见)。
如上面的图片所示,第一个用户可以看到所有物品,没有任何物品是变灰的(因为他们有足够的余额),但是第二个用户没有足够的钱来购买装备。有没有办法从两个不同的商店(ItemStore 和 UserStore)中获取信息以列出所有物品,但是将用户买不起的物品变灰?
下面是我的代码:

(DataView) 物品选择屏幕:

Ext.define("touchstore.view.purchase.ItemSelectionScreen", {
    extend: 'Ext.dataview.DataView',
    xtype: 'item-selection',

    config: {
        store: 'ItemStore',
        itemTpl: new Ext.XTemplate(
            '<tpl for=".">',
                '<div class="item {canAfford}">', //canAfford should be that the users balance is greater than the price of the item
                    '<h1>{itemName}</h1>',
                    '<span>{description}</span><br />',
                    '<div class="cost"><strong>Cost: {cost}</strong></div>',
                '</div>',
            '</tpl>')
    }
});

ItemModel:

Ext.define('touchstore.model.ItemModel', {    
    extend: 'Ext.data.Model',

    config: {
        fields: [
            { name: 'itemName', type: 'string' },
            { name: 'description', type: 'string' },
            { name: 'cost', type: 'int' }
        ]
    }
});

ItemStore:

Ext.define("touchstore.store.ItemStore", {
    extend: 'Ext.data.Store',

    config: {
        model: 'touchstore.model.ItemModel',
        data: [
            { itemName: 'Sword', description: 'Battle your enemies fiercely with this beautiful, yet deadly sword.', cost: 500 },
            { itemName: 'Armour', description: 'Defend yourself from attacks with this beautifully crafted piece of armour.', cost: 1400 },
            { itemName: 'Leather Boots', description: 'Run faster with these lightweight yet stylish boots.', cost: 400 }
        ]
    }
});

UserModel:

Ext.define("touchstore.model.UserModel", {
    extend: 'Ext.data.Model',

    config: {
        fields: [
            { name: 'username', type: 'string' },
            { name: 'balance', type: 'int' }
        ]
    }
});

UserStore:

Ext.define("touchstore.store.UserStore", {
    extend: 'Ext.data.Store',

    config: {
        model: 'touchstore.model.UserModel',
        data: [
            { username: 'steve.smith', balance: 2000 },
            { username: 'robert.junior', balance: 500 }
        ]
    }
});
2个回答

0

假设一次只有一个用户处于活动状态,您无需创建另一个存储库,可以从ItemStore中显示所有项目,并根据当前活动用户和物品价格计算{canAfford}。

您可以使用XTemplate的最后一个参数传递一个带有计算canAfford方法的对象。大致如下:

new Ext.XTemplate(
        '<tpl for=".">',
            '<div class="item {[this.canAfford(values)]}">', //canAfford should be that the users balance is greater than the price of the item
                '<h1>{itemName}</h1>',
                '<span>{description}</span><br />',
                '<div class="cost"><strong>Cost: {cost}</strong></div>',
            '</div>',
        '</tpl>',
        {
            canAfford: function(item) {
                return item.get('cost') <= CURRENT_USER.get('balance') 
                    ? 'CLASS-FOR-CAN-AFFORD' : 'CLASS-FOR-CANNOT-AFFORD';
            }
        })

CURRENT_USER 是指系统中当前活跃的用户的引用。通常,这将来自于登录子系统。假设您实现了一个 LoginController,并具有返回当前已登录用户的 getActiveUser 方法,则可以像这样编写代码(使用 Ext JS):

touchstore.getApplication().getController('LoginController').getActiveUser()

如果使用Sencha Touch,它将是:
touchstore.app.getController('LoginController').getActiveUser()

编辑:

另一个选项是在视图中使用配置文件来传递当前用户信息。您的视图中相关的更改:

Ext.define("touchstore.view.purchase.ItemSelectionScreen", {
    ...

    config: {
        currentUser: null,

        // Empty template so there will be no errors. 
        // The real template is configured in the initialize method.
        itemTpl: '',
        ...
    },
    ...
    updateCurrentUser: function(newUser) {
       this.refresh();
    },

    // Setup the template in the initialize method. The initConfig is
    // probably better for this, but I could not test it.
    initialize: function() {
        var me = this;
        // The template is configured here so it can access me.getCurrentUser().
        me.setItemTpl(new Ext.XTemplate(...));
        me.callParent(arguments);
    }
});

如果您的控制器未实例化视图,则可以在初始化视图事件和/或当前用户更改时初始化此值。

感谢@RicardoMachado。由于DataView本质上是视图层的一部分,它将无法访问应用程序,因此也无法访问“getController”函数。有没有推荐的方法来解决这个问题?另外,如果我想添加一个功能,比如管理员面板,你能推荐如何做吗?基本上,管理员可以输入用户名,并查看他们可能购买的物品(与之前相同的格式-昂贵的物品被变灰)。这是否可能使用户名在飞行中发生变化?再次感谢。 - jamiemcl001
一个选项是在视图中使用配置。这不仅可以保持事物分离(模型、视图和控制器层),还可以允许在运行时更改用户(只需更改配置)。我已经更新了代码,加入了这个选项。 - Ricardo Machado
再次感谢@RicardoMachado。理论上,这将实现我所寻求的目标。不幸的是,XTemplate构造函数的配置对象似乎没有获得正确的作用域,因此无法调用“this.getCurrentUser()”函数。再次强调,这就是我基本上要做的事情。 - jamiemcl001
你可以在类的代码内部创建模板,这样你就可以访问到当前的“this”实例。我已经更新了示例。 - Ricardo Machado

0

我不确定这会不会有效,但你可以试一下,然后告诉我。

Ext.define("touchstore.view.purchase.ItemSelectionScreen", {
extend: 'Ext.dataview.DataView',
xtype: 'item-selection',

config: {
    store: [ItemStore,UserStore],
    itemTpl: new Ext.XTemplate(
        '<tpl for=".">',
            '<tpl if="{balance} &gt; {cost}"',
                '<div>',
                    '<h1>{itemName}</h1>',
                    '<span>{description}</span><br />',
                    '<div class="cost"><strong>Cost: {cost}</strong></div>',
                '</div>',
             '</tpl>',
        '</tpl>')
}
});


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接