I'm faced with problem in ExtJS 4.2, that store.load() method doesn't load data from server, only retrieve json.
My js/itfx/resources/genres.json file:
[{"name":"Action & Adventure","code":"ACTION-ADVENTURE-00"},{"name":"African","code":"AFRICAN-00"},{"name":"Anime","code":"ANIME-00"},{"name":"Bollywood","code":"BOLLYWOOD-00"},{"name":"Classics","code":"CLASSICS-00"},{"name":"Comedy","code":"COMEDY-00"},{"name":"Concert Films","code":"CONCERT-FILMS-00"},{"name":"Documentary","code":"DOCUMENTARY-00"},{"name":"Drama","code":"DRAMA-00"},{"name":"Foreign","code":"FOREIGN-00"},{"name":"Holiday","code":"HOLIDAY-00"},{"name":"Horror","code":"HORROR-00"},{"name":"Independent","code":"INDEPENDENT-00"},{"name":"Kids & Family","code":"KIDS-FAMILY-00"},{"name":"Made for TV","code":"MADE-FOR-TV-00"},{"name":"Middle Eastern","code":"MIDDLE-EASTERN-00"},{"name":"Music Documentaries","code":"MUSIC-DOCUMENTARIES-00"},{"name":"Music Feature Film","code":"MUSIC-FEATURE-FILMS-00"},{"name":"Musicals","code":"MUSICALS-00"},{"name":"Regional Indian","code":"REGIONAL-INDIAN-00"},{"name":"Romance","code":"ROMANCE-00"},{"name":"Russian","code":"RUSSIAN-00"},{"name":"Sci-Fi & Fantasy","code":"SCIFI-FANTASY-00"},{"name":"Short Films","code":"SHORT-FILMS-00"},{"name":"Special Interest","code":"SPECIAL-INTEREST-00"},{"name":"Sports","code":"SPORTS-00"},{"name":"Thriller","code":"THRILLER-00"},{"name":"Turkish","code":"TURKISH-00"},{"name":"Urban","code":"URBAN-00"},{"name":"Western","code":"WESTERN-00"}]
My model:
Ext.define('ITFX.model.films.info.FilmGenre', {
extend: 'Ext.data.Model',
fields: [
{name: 'name', type: 'string'},
{name: 'code', type: 'string'}
]
});
My store:
Ext.define('ITFX.store.films.info.FilmGenre', {
extend: 'Ext.data.Store',
model: 'ITFX.model.films.info.FilmGenre',
proxy: {
type: 'ajax',
url : 'js/itfx/resources/genres.json',
reader: {
type: 'json'
}
}
});
So, after execute code abowe:
var allFilmGenresStore = Ext.create('ITFX.store.films.info.FilmGenre');
allFilmGenresStore.load();
Methods
allFilmGenresStore.getCount(); //0
allFilmGenresStore.getTotalCount(); //0
will return, that store have nothing loaded
What I'm doing wrong?
Thanks in advance
Yes, thanks for assist, the rout cause was, that store data loaded asynchronously. Code for load data, should be:
allFilmGenresStore.load({
callback : function(records, options, success) {
// some custom logik
}
});
You have to change reader
reader: {
type: 'json',
root: 'root'
}
and to send json_encode('root' => $data);
I hope it will help you
Related
Following scenario:
{
xtype: 'combo',
displayField: 'LANGTEXT',
valueField: 'KURZTEXT',
store: {
remoteSort: false,
autoLoad: false,
pageSize: 999999,
fields: [
{ name: 'KURZTEXT', type: 'string' },
{ name: 'LANGTEXT', type: 'string' }
],
proxy: {
type: 'ajax',
url: 'callHandler.cfc',
actionMethods: { read: 'POST' },
reader: {
type: 'json',
rootProperty: 'DATA.ROWS',
totalProperty: 'TOTALCOUNT'
}
},
listeners: {
load: function(store, records, successful, operation, eOpts ){
//is something like this possible?
var combo = store.getCombo()
}
}
}
}
Is it possible to get the combobox reference from the store with something like this: store.getCombo()? I know that normally you can only get the store reference from the combobox. But I thought maybe it works also the other way around, if the store is created in the combobox?
You may want to check the combobox afterQuery template method.
It's a configuration available for the combobox component that works almost similar to the store's load event. Here you have access to both the combobox component and the store.
I think the drawback is: it only gets called when the combo trigger is clicked or a value is typed in the combo's textfield. I believe this would already be help if you want to do your post-processing after these events.
{
xtype: 'combo',
displayField: 'LANGTEXT',
valueField: 'KURZTEXT',
store: {
remoteSort: false,
autoLoad: false,
pageSize: 999999,
fields: [
{ name: 'KURZTEXT', type: 'string' },
{ name: 'LANGTEXT', type: 'string' }
],
proxy: {
type: 'ajax',
url: 'callHandler.cfc',
actionMethods: { read: 'POST' },
reader: {
type: 'json',
rootProperty: 'DATA.ROWS',
totalProperty: 'TOTALCOUNT'
}
}
},
afterQuery: function (queryPlan) {
var combo = queryPlan.combo; // I guess `var combo = this;` should work too..
var store = combo.getStore();
// always return queryPlan
return queryPlan;
}
}
Let me know if you have any issue or questions.
The only solution I could think of was to write a custom matcher function.
You could do this by overriding the Ext.Component and adding the matcher function like this:
Ext.override(Ext.Component, {
hasStoreId: function (storeId) {
if (Ext.isFunction(this.getStore) && this.getStore().storeId) {
return this.getStore().storeId === storeId;
}
return false;
}
});
Now that you have a matcher function for every component you can search for all components with given storeId like this:
Ext.ComponentQuery.query("{hasStoreId('mystore')}");
You can also be more precise and only search for combos that match the criteria like this:
Ext.ComponentQuery.query("combo{hasStoreId('mystore')}");
Now that you have all combos with the given storeId you should easily be able to retrieve the combo you need.
Here a Sencha fiddle with a working example:
example code
I am working with Extjs4.1 MVC. What I am trying to do is save some data to the server but I do not know the proper format or how I should go about submitting the data to the server.
Here is what I am thinking but I do not believe the Ajax call should be in the controller, it should be in the model or in the store file?
method in my controller:
submit: function(value) {
data = {"id": 100, "tdt": "rTk", "val": "445"} // test data
Ext.Ajax.request({
url: 'http://test.myloc.com/providerSvc/dbproxy.php',
params: {
'do':'insert',
'object': 'stk',
'values': data
},
success: function(response){
alert('response.responseText);
}
})
}
My store:
Ext.define('STK.store.Stack', {
extend: 'Ext.data.Store',
model: 'STK.model.Stack',
autoLoad: true,
proxy: {
type: 'ajax',
api: {
read: 'http://test.myLoc.com/providerSvc/dbproxy.php?do=get&object=stack'
},
reader: {
type: 'json',
root: 'data',
successProperty: 'success'
},
writer: {
type: 'json'
}
}
});
my model:
Ext.define('STK.model.Stack', {
extend: 'Ext.data.Model',
fields: ['id', 'tdt', 'val']
});
store.sync() works only when the endpoints for GET and POST are same.
What you can do is, for GET,
set the extraParams by concatenating to the URL or by creating an object like
extraParams[urlKeys] = paramObject[urlKeys];
store.getProxy().setExtraParams(extraParams);
then,
Store.getProxy().setUrl(StoreUrlForGET);
Store.load({
callback : function(rec, operation, success) {
if (success) {}
else {}
});
and for POST write an AJAX request as,
Ext.Ajax.request({
url : StoreURLForPOST,
method : 'POST',
jsonData : Ext.JSON.encode(YourPostData),
success : function(response, request) {},
failure : function(response, request) {}
});
for this AJAX request you can,
Ext.Ajax.setDefaultHeaders({
"TokenId" : TokenValue
});
All of this code goes into your controller.
I think the store is the proper place to make the ajax call.
You can "save" one record by adding it to the store, and then calling the "sync()" function.
Something like this (beware: code not tested):
var store = Ext.create("STK.store.Stack");
var record = Ext.create("STK.model.Stack");
record.set(xvalues);
record.isDirty = true;
record.setDirty(true); // I don't know if this line is required
store.add(record);
store.sync({
success: function(batch, options){
alert("OK!")
},
failure: function(batch, options){
alert("failure!")
}
});
Let's say we follow an original article http://www.sencha.com/learn/the-mvc-application-architecture and have such store:
Ext.define('AM.store.Users', {
extend: 'Ext.data.Store',
model: 'AM.model.User',
autoLoad: true,
proxy: {
type: 'ajax',
url: 'data/users.json',
reader: {
type: 'json',
root: 'users',
successProperty: 'success'
}
}
});
And we decided to implement an infinite scrolling grid. To do that we need to remove autoLoad: true and invoke store.guaranteeRange(...) manually.
So what is the best place for doing so?
Ext.define('AM.store.Users', {
extend: 'Ext.data.Store',
model: 'AM.model.User',
autoLoad: true,
remoteSort: true,
buffered: true,
pageSize: 100,
proxy: {
type: 'ajax',
url: '/postdata/list',
limitParam: 'size',
startParam: undefined,
reader: {
type: 'json',
root: 'data',
successProperty: 'success'
}
}
});
Demo here http://ext4all.com/post/extjs-4-1-grid-infinite-scroll-in-mvc
Somewhere where you render your grid. You can overwrite afterRender() method, or if it's modal grid/dialog - load the store before presenting it.
Couple side note (I'm trying to make a point that autoLoad usually is false for all stores:
if you ever will use any authentication in your application - you
will have to disable autoLoad on all stores.
if you have more then couple stores (say 5-10+?) it's highly recommended to disable that too. You don't want all of them loading at the same time when application is starting.
very often you need to have guarantee that something happened after the store is loaded and then again you disable autoLoad, subscribe to load event and load() the store manually.
I am having a difficult time trying to access xml nodes that are not part of the record.
I would like to get the Success and Price node values.
Thanks!
An example xml would look like this
<Response>
<Success>true</Success>
<Document>
<DocumentHeaders>
<Price>1.99</Price>
</DocumentHeaders>
<DocumentItems>
<DocumentItem>
<Name>Test 1</Name>
</DocumentItem>
<DocumentItem>
<Name>Test 2</Name>
</DocumentItem>
</DocumentItems>
</Document>
</Response>
My data store:
Ext.regModel('DocumentItems', {
fields: [
{ name: 'Name', type: 'string' },
]
});
Ext.regStore('MyStore', {
model: 'DocumentItems',
proxy: {
type: 'ajax',
url: 'Service.asmx/Initialize',
reader: {
type: 'xml',
record: 'DocumentItem',
root: 'DocumentItems'
}
}
});
you can add this property to the reader successProperty: 'success' like this
reader: {
type: 'xml',
record: 'DocumentItem',
root: 'DocumentItems',
successProperty: 'success'
}
And for the price property I don't think there is another way then to modify your model to contain that property.
I've a ScriptTagProxy and I'm able to receive the data, but now I wanted to update a record. I've specified an url but only one url. Do I have to handle all the actions (read, update, create, delete) with this url?
If yes: how does the action is applied to the url?
If not: how I can specify more urls?
Here is the code I have so far:
app.stores.entries = new Ext.data.Store({
model: "app.models.Entry",
storeId: 'app.stores.entries',
proxy: {
type: 'scripttag',
url: 'http://myurl.de/getEntries.php',
extraParams: {
username: Ext.util.JSON.decode(window.localStorage.getItem('settings')).username,
password: Ext.util.JSON.decode(window.localStorage.getItem('settings')).password
},
reader: {
type: 'json'
},
writer: {
type: 'json'
}
}
});
I've read in the docs that you can pass an config object to the save function of a model to configurate the proxy.
So I tried following:
entry.save({
url: 'http://mysite.com/updateEntry.php',
extraParams: {
username: Ext.util.JSON.decode(window.localStorage.getItem('settings')).username,
password: Ext.util.JSON.decode(window.localStorage.getItem('settings')).password,
entry: entry
},}
As you see there is a url specified.
But I still get the error:
Uncaught Error: You are using a ServerProxy but have not supplied it with a url.
);
Same behaviour when using AjaxProxy or RestProxy for example :(
Hering,
With your first block of code you ask:
Question 1) "Do I have to handle all the actions (read, update, create, delete) with this url?"
The answer is yes.
Question 2) "If yes: how does the action is applied to the url?"
According to the Sencha source code you need to define the actionMethods like so:
myApp.stores.Things = new Ext.data.Store({
model: "Things", proxy: {
type: 'ajax',
actionMethods: {
create: 'POST',
read: 'GET',
update: 'PUT',
destroy: 'DELETE'
},
url: 'jsontest.json',
reader: {
type: 'json',
root: 'things'
}
},
autoLoad: true
});
If you delete, create or edit a record you must call:
store.sync();
There is also a "autoSave" property but it only syncs on edits, not removes.
This will send over the things that have changed or been deleted as part of the request payload, it is your responsibility to parse the json and handle it.
Hering,
I was reading the documentation here, I found this example in the Model class:
Ext.regModel('User', {
fields: ['id', 'name', 'email'],
proxy: {
type: 'rest',
url : '/users'
}
});
But above you don't show your Model for app.models.Entry, have you tried that?