Sencha Touch 2 nested models and data stores
extjs, sencha-touch, sencha-touch-2
Solution
This certainly doesn't seem to be utilising the association and store structure that I think Sencha Touch has, but even after progressing to the point of getting the `recipes()` association to load properly, I couldn't ever get this to trigger the dataview to refresh. I was spending too much time on it, so I went with a less elegant solution. I pass the filter text to a setter on the Platter which sets it's store with this filter in the param. It works at least!
Ext.define('NC.view.PlatterDataItem', {
extend: 'Ext.dataview.component.DataItem',
xtype: 'platterdataitem',
config: {
layout: 'vbox',
height: '130px',
cls: 'platter',
list: {
},
dataMap: {
getList: {
setRecipeFilters: 'text'
}
}
},
applyList: function(config) {
return Ext.factory(config, NC.view.Platter, this.getList());
},
updateList: function(newList, oldList) {
if (newList) {
this.add(newList);
}
if (oldList) {
this.remove(oldList);
}
}
});
Ext.define('NC.view.Platter', {
extend: 'Ext.DataView',
xtype: 'platter',
config: {
layout: 'vbox',
height: '130px',
itemCls: 'platter-item',
itemTpl: '<div class="thumb"><tpl if="image != null"><img src="{image}" /></tpl></div>'+
'<div class="name">{name}</div>',
inline: {
wrap: false
},
scrollable: {
direction: 'horizontal',
directionLock: true
}
},
setRecipeFilters: function(text) {
var store = Ext.create('Ext.data.Store', {
model: 'NC.model.Recipe',
autoLoad: true,
proxy: {
type: 'jsonp',
url: 'xxxxx',
callbackKey: 'callback',
extraParams: {
// credentials & text filter param
},
reader: {
type: 'json',
idProperty: 'uuid',
}
}
});
this.setStore(store);
}
});
Problem
I hardly even know how to ask this one, but here goes. I have two models, a Platter which contains many Recipes: ``` Ext.define('NC.model.Platter', { extend: 'Ext.data.Model', config: { fields: [ { name: 'name', type: 'string' }, { name: 'text', type: 'string' } ], associations: [ {type: 'hasMany', model: 'NC.model.Recipe', name: 'recipes', filterProperty: 'text'} ] } }); Ext.define('NC.model.Recipe', { extend: 'Ext.data.Model', config: { fields: [ { name: 'name', type: 'string' }, { name: 'image', type: 'string' }, { name: 'stepsText', type: 'string', mapping: 'properties.preparationText' }, { name: 'ingredientsText', type: 'string', mapping: 'properties.ingredientsText' } ] } }); ``` Platters are basically different filters on an online recipe store. So I might have a thousand recipes but my 'Pizza' platter will only return pizza recipes (thus the filterProperty). Platters are just created and stored locally, whereas Recipes are online. So, the stores: ``` Ext.define('NC.store.Platters', { extend: 'Ext.data.Store', config: { model: 'NC.model.Platter', storeId: 'Platters', proxy: { type: 'localstorage', id: 'platters' }, data : [ {name: 'Noodles', text: 'noodle'}, {name: 'Baked', text: 'bake'}, {name: 'Pizza', text: 'pizza'} ] } }); Ext.define('NC.store.Recipes', { extend: 'Ext.data.Store', config: { model: 'NC.model.Recipe', storeId: 'Recipes', proxy: { type: 'jsonp', url: 'xxxx', // url here (redacted) callbackKey: 'callback', filterParam: 'text', extraParams: { // credentials and tokens here (redacted) }, reader: { type: 'json', idProperty: 'uuid', } } } }); ``` Now, I would like to create a dataview of dataviews. A list of Platters, each containing it's list of Recipes: ``` Ext.define('NC.view.DiscoverGrid', { extend: 'Ext.DataView', xtype: 'discovergrid', id: 'discover', config: { title: 'Discover', baseCls: '', useComponents: true, defaultType: 'platter', store: 'Platters', ui: 'light' } }); Ext.define('NC.view.Platter', { extend: 'Ext.dataview.component.DataItem', xtype: 'platter', config: { layout: 'fit', height: '100px', list: { itemTpl: '{name}', inline: true, scrollable: { direction: 'horizontal', directionLock: true } }, dataMap: { getList: { setData: 'recipes' } } }, applyList: function(config) { return Ext.factory(config, Ext.DataView, this.getList()); }, updateList: function(newList, oldList) { if (newList) { this.add(newList); } if (oldList) { this.remove(oldList); } } }); ``` Now, how do I populate the platter's recipes? If I populate the Platters with a little in-line recipe data like, so: ``` data : [ {name: 'Noodles', text: 'noodle', recipes: [ { name: 'Pasta', ingredientsText: "Tomatoes\nPassata\n1tsp Oregano", preparationText: "Do something\nAdd passata\nmix in oregano and tomato", ingredients: [{ text: "bla"}] } ]}, {name: 'Baked', text: 'bake'}, {name: 'Pizza', text: 'pizza'} ] ``` ... it works straight out and renders the dataview with Pasta in it. So I just need to know how to get my platters to fill their recipe data. Where (I assume in a controller on an initialize event of some sort) and how do I wire this up? And am I using the filterProperty correctly? I don't completely understand the docs on this, but I think it generally filters on a foreign key, which I don't have, and that the filterProperty overrides this. So that the URL will have &text=noodle appended to it. Thanks in advance.