PDA

View Full Version : Changing fields after store is created?



JoelB
6 Jun 2012, 4:40 AM
If I dont know the structure of the data that I wish to load into a store I found that I could create the store with an empty field config:




var myStore = Ext.create('Ext.data.Store', {
fields: [
],
proxy: {
type: 'ajax',
url: 'foo.json',
reader: {
type: 'json',
root: 'users'
}
},
autoLoad: true
});


The store is then created and data is loaded but the model is of course missing. But since I have access to the data as json I can now generate a model (or fields) based on that. Is there some way to configure the fields config property (e.i. metadata) after the store has been loaded?

I found a setConfig function but it doesnt reload anything, and on the reader there is a setModel property, but it doesnt seem to do anything either.

Thanks,
J

sdt6585
6 Jun 2012, 5:04 AM
It would probably be easier to use Ext.Ajax.request() to get the initial data rather than store.load() if you need to build a store based on the data you receive. Just take the response.responseText and run it through the Ext.JSON.decode() function then work with it as normal to build your fields. Then create the store and use the the loadData() function of the store to load the data you got through the Ext.Ajax.request().

Ideally, if you've got control of the server side environment, you could make a store builder url that takes the same parameters as your other query and just returns the field names/types/etc, then use the normal store.load() after you've got the store/model built.

JoelB
6 Jun 2012, 5:20 AM
Thanks sdt6585,

The thing is that I need the store to be a rest loaded store that possibly only loads parts of a much larger data set depending on what is viewed in say a table. Of course I could set up a serverside URL to give me the model config needed first and then the use that model when creating the store, but since the rest of the clientside framework is using other non-ext stores that does not need this url, it feels like I am doing a workaround where I figured it should be possible to just infer the model config based on the selected data.

I guess though that the solution lies in a second ajax call to get the field setup before creating the store. :(

sdt6585
6 Jun 2012, 6:37 AM
I don't believe that it will infer the fields for you, but it would be easy enough to do yourself in code. If it's only used in one or two locations, I would do it in the controller or main script, otherwise, I would extend the base store class to try and infer the field info if no field definition is present in the constructor. Haven't tested it, but something like this:



Ext.define('Ext.ux.data.Store', {
extend: 'Ext.data.Store',


constructor: function(config) {
//Check for field or model definition
if (typeof config.model === 'undefined' && typeof config.fields === 'undefined') {
Ext.Ajax.request({
url: config.proxy.api.read,
scope: this,
success: function (response, opts) {
response = Ext.JSON.decode(response.responseText);
//Get first record - may have to loop through all with inconsistent data
var record = response.data[0];
//Build the fields config
config.fields = [];
for (key in record) {
config.fields.push(key);
}
//Call default constructor
this.callParent(arguments);
},
failure: function() {/*handle errors*/}
})
} else {
this.callParent(arguments);
}
}
});

JoelB
7 Jun 2012, 12:48 AM
This still requires 2 queries. I would like/need to infer the model from the data received.

Who is actually making the query and when is it actually populating the datastore?
Would it somehow be possible to extend some class somewhere when the data returns, and then create the fields definition in the data store, before letting the data populate it?
Or is this too late already?

Thanks for all help.
//J

JoelB
7 Jun 2012, 1:32 AM
Ok Partly resolved:


var myStore = Ext.create('Ext.data.Store', {
fields: [],
proxy: {
type: 'ajax',
url: 'labb.json',
reader: {
type: 'json',
root: 'users'
}
},
autoLoad: true
});
Ext.define('User', {
extend: 'Ext.data.Model',
fields: [
{name: 'name', type: 'string'},
{name: 'age', type: 'int'},
{name: 'type', type: 'string'}
]
});


myStore.getProxy().getReader().setModel("User");


myStore.read()




My question is now: Can I do this without defining a new named Model everytime? It seems like a very unnecessary step that could be memory hogging?
Or can I create unnamed modeles, or can I reuse the same name for many models without affecting stores using them?
Or should I use a guid for a name?

//J

JoelB
7 Jun 2012, 2:57 AM
Solved:
- Just not do the read at end and theres no extra requests.
- Since I set the model on the reader it is inferred on the store causing the implicitModel property to be set which will destroy the model when the store is destroyed, making guid names perfectly ok.



var myStore = Ext.create('Ext.data.Store', {
restful: true,
autoLoad: true,
autoSave: true,
fields: [],
proxy: {
type: 'ajax',
url: 'labb.json',
reader: {
type: 'json',
successProperty: 'success',
idProperty: 'name',
root: 'users'
},
writer: {
type: 'json',
encode: false,
writeAllFields: true
}
}
});
Ext.define(someclass.getGuid(), {
extend: 'Ext.data.Model',
fields: [
{name: 'name', type: 'string'},
{name: 'age', type: 'int'},
{name: 'type', type: 'string'}
]
});

myStore.getProxy().getReader().setModel("User");



//J