Extjs sencha touch 2:将关联数据绑定到现有存储
我有一个简单的数据模型,看起来像这样(下面是实际代码): 我想要的似乎很简单。我已经有了大量加载游戏和游戏分数的代码。我手头有一个“游戏”实例,可以调用gameScores()。我有一家商店,但它是空的。我的代码将动态加载它,方法是将存储放在模型的hasMany定义中。但是我真正想要的是某种方式来绑定Game.gameScores()调用到我现有的gameScores商店。即使它在下面使用了一个普通的过滤器,这也给了我一条记录,我可以在视图中绑定和使用它。(重要提示:数据不是嵌套形式。) 这引出了我的第二个问题。游戏:游戏分数为1:多,但我只显示最近的一个(来自实时分数报告)。这里的一般做法是什么?我也可以从游戏id手动构建一个过滤器,但我只能将一条记录绑定到一个视图,因此我不知道如何将其他信息带入视图,除非有正确的hasMany关系。还有别的办法吗 任何和所有的建议,包括告诉我RTFM(与相关手册的链接),将不胜感激!上个星期我一直在为这个(公益性的项目)忙得不可开交 干杯 bExtjs sencha touch 2:将关联数据绑定到现有存储,extjs,touch,store,has-many,Extjs,Touch,Store,Has Many,我有一个简单的数据模型,看起来像这样(下面是实际代码): 我想要的似乎很简单。我已经有了大量加载游戏和游戏分数的代码。我手头有一个“游戏”实例,可以调用gameScores()。我有一家商店,但它是空的。我的代码将动态加载它,方法是将存储放在模型的hasMany定义中。但是我真正想要的是某种方式来绑定Game.gameScores()调用到我现有的gameScores商店。即使它在下面使用了一个普通的过滤器,这也给了我一条记录,我可以在视图中绑定和使用它。(重要提示:数据不是嵌套形式。) 这引出
我从未使用过touch,所以我在这里谈论Ext4(精确地说是4.2)。。。而且,对我来说,你的模型定义似乎有点不正确(这是否适用于触摸?)。但不管怎样,你都会明白的。如果我的代码在touch中不起作用,请尝试使用Ext4 另外,我知道你正在一次加载所有分数。如果不是这样,我的解决方案将需要调整 因此,我的一般推理如下:如果您已将所有分数加载到内存中,那么为什么不使用内存代理,将分数存储的数据用作为关联生成的存储的数据源?我试过了,令我惊讶的是,它没有出现故障 要理解这一点,您需要知道代理是一个独立的数据源,也就是说,代理可以在多个存储之间毫无问题地共享。另一方面,存储应绑定到单个视图或任务。例如,如果将同一存储绑定到两个不同的网格,则过滤第一个网格也会影响第二个网格 虽然大多数代理并不“包含”它们的数据,但内存代理却包含。下面是
Ext.data.proxy.Memory#read
方法的相关摘录:
resultSet = operation.resultSet = me.getReader().read(me.data)
因此,足够的理论,这里是概念证明(在本文中测试):
关于你的其他问题
如果游戏分数为1:n,那么游戏分数为1:1。。。所以,我会尝试使用它
至于视图,应该总是有一种方法——即使是黑客——来访问嵌套在记录中的数据。方法将取决于您在此处所称的视图。。。请看,例如这个。我从未使用过touch,所以我在这里讲的是Ext4(精确地说是4.2)。。。而且,对我来说,你的模型定义似乎有点不正确(这是否适用于触摸?)。但不管怎样,你都会明白的。如果我的代码在touch中不起作用,请尝试使用Ext4 另外,我知道你正在一次加载所有分数。如果不是这样,我的解决方案将需要调整 因此,我的一般推理如下:如果您已将所有分数加载到内存中,那么为什么不使用内存代理,将分数存储的数据用作为关联生成的存储的数据源?我试过了,令我惊讶的是,它没有出现故障 要理解这一点,您需要知道代理是一个独立的数据源,也就是说,代理可以在多个存储之间毫无问题地共享。另一方面,存储应绑定到单个视图或任务。例如,如果将同一存储绑定到两个不同的网格,则过滤第一个网格也会影响第二个网格 虽然大多数代理并不“包含”它们的数据,但内存代理却包含。下面是
Ext.data.proxy.Memory#read
方法的相关摘录:
resultSet = operation.resultSet = me.getReader().read(me.data)
因此,足够的理论,这里是概念证明(在本文中测试):
关于你的其他问题
如果游戏分数为1:n,那么游戏分数为1:1。。。所以,我会尝试使用它
至于视图,应该总是有一种方法——即使是黑客——来访问嵌套在记录中的数据。方法将取决于您在此处所称的视图。。。例如,看看这个。Wow。这是一个奇妙的开始!谢谢稍后我会尝试一起破解。一个区别是,游戏实际上是动态加载的——但只需要很少的刷新,所以同时刷新相关分数是很方便的。此外,这种缓存概念也适用于其他事物。这是一个奇妙的开始!谢谢稍后我会尝试一起破解。一个区别是,游戏实际上是动态加载的——但只需要很少的刷新,所以同时刷新相关分数是很方便的。此外,这种缓存概念也适用于其他事物。
resultSet = operation.resultSet = me.getReader().read(me.data)
// I instantiate this proxy myself in order to have a reference available
var masterScoreProxy = Ext.create('Ext.data.proxy.Memory');
Ext.define('TouchMill.model.GameScore', {
extend: 'Ext.data.Model',
fields: [ 'id', 'game_id', 'team_1_score', 'team_2_score', 'is_final', 'submission_date' ],
// I've used a remote server to ensure this all works even asynchronously
proxy: {
// configure your own
}
});
Ext.define('TouchMill.model.Game', {
extend: 'Ext.data.Model'
,fields: [ 'id', 'team_1_id', 'team_2_id' ]
,hasMany: {
model: 'TouchMill.model.GameScore'
,name: 'gameScores'
// required in order to avoid Ext autogenerating it as 'touchmill.model.game_id'
,foreignKey: 'game_id'
// needed if we don't want to have to call gameRecord.gameScores().load()
,autoLoad: true
// first part of the magic: make the generated store use my own proxy
,storeConfig: {
proxy: masterScoreProxy
}
}
});
// Just mocking a store with two games
var gameStore = Ext.create('Ext.data.Store', {
model: 'TouchMill.model.Game'
,data: [{id: 1}, {id: 2}]
,proxy: 'memory'
});
// Creating the "master" score store (that will use the model's proxy)
var scoreStore = Ext.create('Ext.data.Store', {
model: 'TouchMill.model.GameScore'
// second part's in there
,listeners: {
load: function(store, records, success) {
if (success) {
// 1. replace the data of the generated association stores' proxy
// (I must say I'm quite surprised that I didn't had to extract the data of
// every records, nor to configure a reader and all for my shared proxy...
// But hey, that works!)
masterScoreProxy.data = records;
// 2. update already generated stores
// Alternatively, you could call gameRecord.gameScores().load() individually
// before each usage of gameRecord.gameStores()
gameStore.each(function(record) {
var childStore = record.gameScoresStore;
if (childStore) {
childStore.load();
}
});
}
}
}
});
// test first load
scoreStore.load({
callback: function(records, operation, success) {
if (success) {
// and here's to prove it
gameStore.each(function(record) {
record.gameScores().each(function(score) {
console.log('Game ' + record.id + ': ' + JSON.stringify(score.data, undefined, 2));
});
});
testRefreshedData();
}
}
});
function testRefreshedData() {
// test refreshing
scoreStore.load({
callback: function(records, operation, success) {
if (success) {
console.log('--- Scores have changed ---');
gameStore.each(function(record) {
record.gameScores().each(function(score) {
console.log('Game ' + record.id + ': ' + JSON.stringify(score.data, undefined, 2));
});
});
}
}
});
}