How to selectively populate a Store in Sencha Touch 2 - extjs

I have the following store in my Sencha Touch 2.4.1 application:
Ext.define('NativeApp.store.Item', {
extend: 'Ext.data.Store',
config: {
model: 'NativeApp.model.Item',
storeId: 'item-store',
fields: ['id', 'description'],
proxy: {
type: 'ajax',
url: 'resources/json/item.json',
reader: {
type: 'json',
rootProperty: 'items'
}
},
autoLoad: true
}
});
It's being populated with everything in the JSON file, which let's say looks like this:
{
"items": [
{
"id": 's1',
'description': 'desc'
},
{
"id": 's2',
'description': 'desc'
}
]
}
Let's say that in my view I have two buttons, "s1" and "s2".
If I click on "s1", I am taken to a page with a list that contains the data with id "s1". (In this case, there is only one, but there could be more).
How would this be accomplished?
Idea 1:
The autoload attribute can be set to an Object. From here - "If the value of autoLoad is an Object, this Object will be passed to the store's load() method."
So if in my controller, in the handler that's executed when the button is tapped, I can generate this object (parse the JSON file) and somehow pass it to the store - mission accomplished. Sort of.
Besides the question of how to pass it to the store, the immediate problem is when is the data loaded into the store?
According to the docs, "this store's load method is automatically called after creation". Is creation when the app launches, or when I create the view object that uses the store:
var view = {xtype: 'myview'};
Idea 2:
Maybe I could dynamically switch out the url from the proxy and have separate JSON files for each id (there won't be too many). But that seems unlikely to work.
Idea 3:
Pass in a data object to the store (again parsing the JSON) from that controller.
Are any of these feasible? And if not, what is an alternative solution?Perhaps I'm overthinking this.
Edit:
I have a list of items, and each item has a list of sub-items. So when I select one item, I want to be taken to page of the sub-items. Right now, all of these sub-items are in one JSON file, so after clicking on one item, I need a way of telling the store to load only part of the json data.
Is Ext.data.model.load still the best approach?

Idea 1:
Yes, you could do that... probably more trouble than it's worth IMO. The store will load immediately after it is created -- so if you create the store at application start, then it loads then. If you create a store randomly during runtime, it loads then. If the store is defined inline for a view, it's loaded when the view is created.
Idea 2:
Arguably a better solution, but still a lot of trouble to swap the URL for the proxy, then forcibly load it, parse the data, etc.
Depending on your view, you could just directly load the data for a single model using NativeApp.model.Item.load(id) (see docs). This assumes you have an API setup for that, but it's easier IMO and certainly more RESTful.
Idea 3:
Meh. It really sounds to me like Ext.data.Store is the wrong construct for what you're trying to accomplish.
Are any of your ideas feasible? Yes.
Are you over-thinking this? Slightly, but then again you wouldn't be a programmer if you didn't.
It's hard to tell you exactly what I'd do without seeing the rest of your application and understanding the WHY you're doing X, Y, or Z... but if you're only planning on displaying a single model's data on a given "Detail" screen (and you need that data loaded on-demand), then the static Ext.data.Model.load() method is probably what you need.

Related

In Sencha Touch, how do I notify all stores associated with a model after calling MyApp.MyModel.load()

How do I notify all stores associated with a model after calling MyApp.MyModel.load()? Alternatively, is there a way to load 1 record by Id from the context of a store?
My ultimate goal is to fetch one single record from the server and refresh a list that is bound to a store that has the record in it.
Don't do a Myapp.model.load. Use store.load instead.
Because what you really want to do is this:
function refreshSingleItem(store,id) {
store.remove(store.getById(id));
store.getProxy().setExtraParam("id",id);
store.load({addRecords:true;});
}
When you load a store, all records are loaded into that store. You wouldn't want anything else, because you would not have to load everything over the wire if you don't store it on the client side.
It is not possible to do one call and have all stores updated which have that call in their url. It will only update one store, everything else you will have to code by yourself.
That said, you can always make a second store with the same model, and load a single record from the first store into the second:
store1.on('load',function() {
store2.add(store1.getById(recordId));
});
VoilĂ , now you have a store with only one record and you can load any other record as desired. But this is needed less often than the other way round. So let's say you have a record:
data:[{
meetingId:123,
time:'2014-09-16T17:40',
location:'1 Washington Drive, room #1203'
participants:[{
name:'John Doe',
phone:'46318123'
},{
name:'Jane Doe',
phone:'477119524'
},{
name:'George Washington',
phone:null
}]
}]
You could then define participants as a field without type in model1, make a model2 with name and phone, and do the following:
store1.on('load',function() {
form.loadRecord(store1.getAt(0));
store2.add(store1.getAt(0).get("participants"));
});

Accessing piggybag property from a ExtJs JsonStore, is it possible?

Let's say I have a ExtJs Grid that utilizes a JsonStore for a dataset like:
{
mode: 'piggy',
records: [
{name: 'record1',...},
{name: 'record2',...}
]
}
rooting at records, the grid displays fine. Now is it possible that I can access the "mode" property from the store object? It contains some metadata about my grid beside the row data, and it certainly seems like a waste to open another Ajax connection to the server to get a metadata value. Anyone has done that?
You should still have access to the raw JSON data that came back in the response.
There are probably multiple ways to get to it but here is one:
store.proxy.reader.rawData or jsonData

How to reuse store in EXT JS 4 MVC application without multiple reloading?

I am working on extjs 4 MVC application.
Application runs the Viewport, which contains tabpanel.
Each tab has own controller and multiple views.
See my sandboxs at http://wap7.ru/folio/ext-reuseable-store/TE.html
I have one Store used several times (e.g. one tab in topmenu combobox, another in the clietns grid.)
Store configured with autoload: true.
Proxy is configured in the Model.
My problem: Store is loaded multiple times - at every mention in the controller [stores] array.
If I remove one from the array [stores] controller- combobox will be empty, although it states store: Ext.getStore ('STORE-ID')
Please give me a hint, or an example of re-using Store (not Model) as in here http://docs.sencha.com/ext-js/4-0/#!/guide/mvc_pt2
You can just instantiate your store and load it, remove the autoload.
var store = Ext.create('App.store.YourStore').load();
Then pass that store to all your components, just like you would do when you want a paging bar connected to a grid.
This normally works fine to call your store from other controllers:
Ext.getStore('PlatformClient');
I've never tried to put the same store in more than one controller stores array. That seems strange to me.
There are a couple of other oddities about the code you have posted though, maybe they're just typos and maybe they don't make any difference to the framework but they're different from what I normally do so I'll point them out:
First, your model array in the "typical controller" contains a store:
models:[
'te.store.PlatformClient'
],
That one is probably just a typo.
Second, I don't put the full namespace in my store arrays, this is something that may not make a difference, but I don't know. Maybe ExtJS is prepending the namespace on top of the namespace you have written out so it thinks that you are instantiating a different store whenever it initializes a new controller - thereby causing it reload. For example this is more "normal" for whatever it's worth:
stores:[
'Taxonomy',
'PlatformClient',
'DataType'
],
controllers:[
'Taxonomies' ,
'DataType' ,
'DataSale' ,
'Clients'
],
Try setting it up like that and get rid of the duplicative stores in the other controller store arrays.
Also, I want to make sure that you caught the bit in the docs about not needing to define a storeId config for MVC stores. The framework will automatically give the store this:
storeId: [StoreClassName]
So in your example, you would get this automatically:
storeId: 'PlatformClient'
Someone else had trouble with MVC stores recently and it traced back to the framework being flabbergasted by the audacity of the dev supplying their own storeId config with the MVC pattern.
We used to have similar problems with loading. Also got issues with filtering in case of multiple use of the same store (you may want to set filter on one but not on the other). Therefore we load all the stores at application launch. Then whenever we need that store for displaying purposes then instead of using the original we are cloning it in the memory with ha utility function as below.
/**
* Use this for example if you want to apply a filter on a store
* but you dont want the original store to change, so:
* singleton store has no filter
* you clone it to be used with filters in some places.
*
* Note: this will have memory proxy, so no changes to the stores are persistent,
* changes will have no effect on the local/remote db.
*
*/
createStore: function(storeId, data) {
//
// Creates a new store from the given array of records without
// registering the new store.
// See cloneStore for more info
//
var modelName = storeId;
var prevStore = Ext.getStore(storeId);
data = data || prevStore.data.all;
var clonedStore = Ext.create('App.store.' + storeId, {
data: data,
model: 'App.model.' + modelName,
proxy: 'memory'
});
Ext.data.StoreManager.register( prevStore );
return clonedStore;
}
Please note the cloned copy is using memory proxy. Therefore write operations shouldn't be done on it. If you need to update the store then always use the original.
I hope this helps on some way.

Extjs 4 Ext.data.Model: How to model nested objects

I'm new to Extjs 4 and I'm trying to understand how to create a model for data that has nested objects.
Example Data:
{
data1:{
field1:1,
field2:2,
**objField1**:{
objField1:1,
objField2:2,
**anotherObj**:{
field1:1,
field2:2,
arrayofObjs:[
{
//...
},
//...
]
}
},
objField2:{
//... Some more fields or objects
},
data2:{
//...
}
}
I'm trying to understand how I would model this data. The fields are easy
Ext.define('MyModel', {
extend: 'Ext.data.Model',
fields: [
{name: 'field1', type: 'int'},
{name: 'field2', type: 'int'}
], //...
But how do you model the objects? I was thinking I could create a model for the sub-objects and setup associations, but after reading the documentation, they seem to need to have IDs. So if you look at the belongsTo page, "The owner model is expected to have a foreign key which references the primary key of the associated model".
I'm not looking to model data that has foreignkey relationships, just objects with sub-objects. So the server might return one JSON object with multiple sub-objects, and one of those objects I might want to tie to a grid, another object's data to a selectbox, etc.
Thanks!
I think you have several problems here.
First, Models in Ext JS are mostly used to represent relational data, i.e. rows in SQL database. You can twist them to do whatever you want, but that doesn't mean it would be easy and there's always the question of "what for".
Second, Ext.data.Model is not suited at all for representing tree-like structures; you can use Ext.data.NodeInterface for that. NodeInterface is kinda class override for Model, a mixin in part, and generally is quite kludgy and rigid thing. The bright side is that it works, and the down side is that there's no other class that does the same stuff.
Next, nested data objects do not necessarily mean that they're actually related to each other. You said you want to pluck objects from one global JSON response; this can be done easily by configuring multiple Stores with different Readers and feeding them the same JSON object.
OTOH, the data structure looks a bit convoluted. Is that an attempt at preliminary optimization on the server side? I.e., put all stuff we might need into one huge JSON to save on server hits? If so, take a look at Ext.Direct remoting; it can save you from lots of headache down the road.

ExtJS Ajax vs Extjs Store for single row from server

Scenario: I have a URL that returns details about the current logged in user. I.e.
one record
no list needed
Options I have:
Perform a manual ExtJS Ajax call each time, having to insert the code everywhere I need the callbacks etc.
Create an ExtJS Store once and fetch the first record from the store instance every time.
Question: Any better options? I'm using ExtJS 4.1.
You don't need to go into low level details to do something like that; use the standard tools. Define a Model, assign it a Proxy of the type you need, and load it. See the docs: http://docs.sencha.com/ext-js/4-1/#!/api/Ext.data.Model
Why are you doing an ajax call each time?
Do it once, and assign it as a global variable?
Ext.Ajax.request({
url: 'page.php',
params: {
id: 1
},
success: function(response){
var text = response.responseText;
window.user = Ext.JSON.decode(text);
my.custom.launchFunction();//does your viewport etc for you
}
});
Having done this, you can now, from anywhere do
console.log(user.Name);
Its neater, and faster, than doing a store lookup.
As a bonus, you user object can be much more complex than the store would handle without a ton of config.

Resources