PDA

View Full Version : Ext.data.Store.load() populates store on first call only



sweishaar
27 Apr 2012, 12:07 PM
Hello,

I have a fairly straight forward page that supports multiple contexts based on the configuration data returned from the server. I have a datastore with an AJAX proxy setup and a JSON reader with autoload set to false. When I open the page in the controller onLaunch() function I get a reference to the store manager for this store and call ConfigurationStore.load() which proceeds to load the data store as expected and the page works fine.

The issue I'm encountering is that under certain circumstances based on user action I need to re-load the configuration data store to get the current state and take the appropriate actions on the page. Problem is just as in the onLaunch I get a reference to the same datastore but when I call ConfigurationStore.load() it does nothing. No errors, no ajax call to the server, nothing.

Any ideas as to why this would be? Doesn't matter if the data in the store has been modified or not (sometimes there is an intermediate AJAX post to the server to store current state information, other times not, just the user wanting to refresh the page to the original state). If I actually do a page refresh it reloads the data, but that is not a viable solution as I need to preserve state information on the client and simply need the load() to make the AJAX call to get a fresh set of configuration data to control the loading of other information and/or set control states based on background processes that occur and affect what the user can and cannot be allowed to do.

TIA

vietits
27 Apr 2012, 4:33 PM
Could you post your code related to the problem you mentioned? It's difficult to say without looking at your code.

sweishaar
27 Apr 2012, 6:31 PM
There isn't much to show. The datastore is mostly the defaults accept for unchecking autoload and the function that both works and doesn't simply looks up the data store manager for it and the calls load(). But here it is (datastore, model, then code). code is same two lines just called from different places. Even put it in a button clicked with nothing else and it does nothing though same code works onLaunch.
---------------------------- data store start --------------------------------------
Ext.define('SCCat.store.ConfigStore', {
extend: 'Ext.data.Store',
requires: [
'SCCat.model.ConfigModel'
],

constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
autoLoad: false,
storeId: 'ConfigStore',
model: 'SCCat.model.ConfigModel',
proxy: {
type: 'ajax',
url: '/config/ScoreCard.aspx?o=393',
reader: {
type: 'json',
root: 'rows'
}
},
listeners: {
beforeload: {
fn: me.onJsonstoreBeforeLoad,
scope: me
},
load: {
fn: me.onJsonstoreLoad,
scope: me
}
}
}, cfg)]);
}
});
---------------------------- data store end --------------------------------------

---------------------------- Model start -----------------------------------------
Ext.define('SCCat.model.ConfigModel', {
extend: 'Ext.data.Model',

fields: [
{
name: 'Context',
type: 'string'
},
{
name: 'DataState',
type: 'string'
},
{
name: 'ConfigVersion',
type: 'int'
},
{
name: 'VersionDate',
type: 'string'
}
]
});

---------------------------- Model end -----------------------------------------
---------------------------- COde----- -----------------------------------------

onLaunch: function() {
var tConfigStore = Ext.StoreMgr.lookup('ConfigStore');
tConfigStore.load();
}

vietits
27 Apr 2012, 6:39 PM
What does onJsonstoreBeforeLoad look like?

srweishaar
28 Apr 2012, 7:57 AM
I have no event code for the beforeLoad on this datastore, there are no conditions under which I block the load from occurring (in other words I never need to return false to stop the load so I have no event code handler written for it).

vietits
28 Apr 2012, 4:46 PM
It's strange!

FYI: I have tried to simulate your case with the following codes and it works well.
1. app.js


Ext.Loader.setConfig({
enabled: true,
disableCaching: true,
paths: {
SCCat: '.'
}
});
Ext.application({
name: 'SCCat',
autoCreateViewport: true,
controllers: [
'ConfigController'
]
});

2. Controller


Ext.define('SCCat.controller.ConfigController', {
extend: 'Ext.app.Controller',


stores: ['ConfigStore'],
models: ['ConfigModel'],


init: function() {
this.control({
'grid button[action=load]': {
click: this.loadData
}
});
},
loadData: function() {
var tConfigStore = Ext.StoreMgr.lookup('ConfigStore');
tConfigStore.load();
},
onLaunch: function() {
var tConfigStore = Ext.StoreMgr.lookup('ConfigStore');
tConfigStore.load();
}
});

3. Model


Ext.define('SCCat.model.ConfigModel', {
extend: 'Ext.data.Model',


fields: [{
name: 'Context',
type: 'string'
},{
name: 'DataState',
type: 'string'
},{
name: 'ConfigVersion',
type: 'int'
},{
name: 'VersionDate',
type: 'string'
}]
});

4. Store


Ext.define('SCCat.store.ConfigStore', {
extend: 'Ext.data.Store',
requires: [
'SCCat.model.ConfigModel'
],
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
autoLoad: false,
storeId: 'ConfigStore',
model: 'SCCat.model.ConfigModel',
proxy: {
type: 'ajax',
url: 'app.json',
reader: {
type: 'json',
root: 'rows'
}
},
listeners: {
beforeload: {
fn: me.onJsonstoreBeforeLoad,
scope: me
},
load: {
fn: me.onJsonstoreLoad,
scope: me
}
}
}, cfg)]);
},
onJsonstoreBeforeLoad: function(){
console.log('beforeload')
},
onJsonstoreLoad: function(){
console.log('load')
}
});

5. Viewport


Ext.define('SCCat.view.Viewport', {
extend: 'Ext.container.Viewport',


layout: 'fit',
items: [{
xtype: 'grid',
store: 'ConfigStore',
tbar: [{
text: 'Load Data',
action: 'load'
}],
columns: [{
header: 'Context',
dataIndex: 'Context',
flex: 1
},{
header: 'DataState',
dataIndex: 'DataState',
flex: 1
},{
header: 'ConfigVersion',
dataIndex: 'ConfigVersion',
flex: 1
},{
header: 'VersionDate',
dataIndex: 'VersionDate',
flex: 1
}]
}]
});
6. Data app.json


{
"success": true,
"rows": [{
"Context": "Context 1",
"DataState": "DataState 1",
"ConfigVersion":1,
"VersionDate":"VersionDate 1",
},{
"Context": "Context 2",
"DataState": "DataState 2",
"ConfigVersion":2,
"VersionDate":"VersionDate 2",
}]
}

sweishaar
28 Apr 2012, 5:57 PM
I notice you have caching disabled, which I do not. Possible relation?

I added a test button that in the clicked event has two lines, getting the refererence to the datastore from the store manager using the lookup() function;
calling the configStore.load(); function.

In firefox, firebug it doesn't even send the get to the URL specified in the proxy, it does nothing.

Same code in onLaunch when the datastore has no data loaded (and thus no cache) it sends the get to the URL and everything works fine.

It is the ONLY thing I see that is different other than you have a beforeload event with logging in it. I've put in logging to verify that the code is executing, and it is, it simply doesn't do anything if there is already data in it. Caching catches my eye as the real significant difference as this is about as basic of a datastore load process as I can imagine, the complexity is 100% on the server side, but it isn't getting called accept the first time load() is called for the mystery reason.

Thanks!

gnube
28 Apr 2012, 7:46 PM
Clutching at straws but: by any chance do you have multiple config stores on the page? The storeid should be unique.

sweishaar
28 Apr 2012, 8:12 PM
No multiples, only one configStore required and the id is most definitely unique from the other stores. Feeling like a "feature" in which documentation is in the making right here. Why load() would actually cause the code to execute when never having been loaded before but afterwards simply do nothing (no error, no HTTP communication, nothing, just calls the method with absolutely no response action resulting, it just doesn't behave like an error, it behaves like somewhere in the internals it doing some sort of check and whatever the condition it is checking for to not load is being met and so it does nothing. Because the execution time is instant. the load event does not fire, so it is not attempting and failing it is simply not attempting as evidenced by no communication to the server. But why would you want to block your data structures from loading on demand. It is like executing a call to a sql statement that only executes and returns a result set the first time. If you didn't want it to load again simply write the code so your not trying to under whatever those conditions are. Why based on some configuration only execute the call through the proxy the first time, makes no sense. Thinking out loud here as it just doesn't make sense. Still makes me wonder about the cache, but only because that is the difference I see not because it makes sense to not load it again if cache is true. I should be able to load it 1000 times in row if need be.

sweishaar
28 Apr 2012, 8:21 PM
Noticed I don't have a nocashe property to set that I see in architect, where is that getting set?

TIA

gnube
28 Apr 2012, 8:22 PM
I always place my proxy onto my model, not the store - you could give that a try - remove proxy from the store of course.


Ext.define('App.model.ControlGroup', {
extend: 'Ext.data.Model',
fields: [ {name: 'id', type:'string' },
{name: 'code', type:'string', defaultValue: '-New-'},
{name: 'name', type:'string',defaultValue: '-New-'}
],

proxy: Ext.create( 'Ext.data.proxy.Rest',{
//yadda yadda yadda
})

});

sweishaar
28 Apr 2012, 8:31 PM
I'm taking what architect generates, but I could move it for testing purposes though given everything else on the page works exactly how I want I'm hisitant to make structure changes at this point other than to test. But I have seen some peculiar changes in behavior from changing structure even if it is the defalt that is generated so it is worth a try.

I'll try it in the morning, getting tired and don't want to make fatigue mistakes at this point.

I'll post results.

vietits
28 Apr 2012, 11:53 PM
As sweishaar said, I think the problem maybe at not disable caching. Without preventing caching, if the request is the same as previous request (as in this case), browser will use the loaded data in its cache instead of re-sending request to server to get new data. Let have a try by setting disableCaching to true.

sweishaar
30 Apr 2012, 9:07 AM
Moving proxy to model had no effect. Editing the generated achitect app.js to add nocache=true didn't fix it but broke a couple of other things. So thanks for suggestions, but nothing so far has helped. I'm still listening though.

One aspect I never mentioned that may be pertinent is that this datastore has no visible control for showing the data. It is a "cache" of configuration and state information that determines page mode and context but is not visible (except the serialized JSON I write to the log for debug).

sweishaar
2 May 2012, 11:53 AM
Since I started it, I'll finish it as I found the solution to the problem. For a reason I do not know I have to set the URL on the proxy each time before calling load(). If I do this, the proxy sends the HTTP GET to the server at the specified URL and the datastore is populated. If I reset the URL value prior to calling ConfigStore.load() then the HTTP Get is sent and my data refreshed. If I don't reset the URL, even though I am setting it to the same exact value as was in there before, it doesn't send the HTTP Get.

Maybe with that detail Sencha can answer why it is necessary to reset the URL value on the proxy prior to calling load() every time you want to refresh the data in the datastore. This is not being used in a CRUD context, it is read only and based on a variety of activities by both the user, data loads on the server, and batch processes running on the server this ConfigStore (named for configuration store) controls how the page is configured so it conforms to the current state of the server. All is working now, but this behavior is totally unexpected and not defined as necessary. So as I said, if with this additional information an answer can be provided it would be great.

TIA