I am using extjs(4.1.0) MVC .
I have a custom grid set up with combo box filter, datepicker filters etc. I am attaching snippets from the controller, view, and store.
I response coming in is different from the model, hence, the response is intercepted by overriding a read() of the story proxy.
Also data needs to be sent as Json data in payload, so the buildRequest() of store proxy is also overridden to add json data to request. (all sort, paging params are also added here)
Adding to this - the view has infinite scrolling.
The view loads fine the first time. But on combobox change/date change, store is reloaded with passing these as json params in request.
I see the response in XHR in firebug/chrome, but the grid continously shows the loading mask, waiting for loading.. Kindly help on what could be going wrong.
Ext.define('Message.store.ListingStore', {
extend: 'Ext.data.Store',
model: 'Message.model.ListingModel',
autoLoad: true,
remoteSort: true,
purgePageCount:0,
buffered: true,....
.......
proxy: {
type: 'ajax',
actionMethods: {
read: 'POST'
},
url: 'http://localhost:8080
buildRequest: function(operation) {
Ext.apply(request, {
params: null,
jsonData: Ext.apply(request.params, {
page: operation.page,
start: operation.start,
limit: operation.limit,
catId:catValue,
sort:operation.sorters[0].property,
dir:operation.sorters[0].direction
})
});
........return request;
}
root: 'data',
totalProperty:'total',
successProperty :'success'
},
.....
});
//controller
Ext.define('Message.controller.Listing', {
extend:'Ext.app.Controller',
stores: ['ListingStore','SubscriptionStore','SubCategoryMasterStore','PriorityMasterStore'],
models: ['ListingModel'],
views: [
'MessageListing'
],
init:function () {
var controller = this;
'messagelisting combo' : {
select : this.handleComboSelect
},
'messagelisting datefield' : {
select : this.handleDateSelect
},
.....
handleComboSelect : function(gridview, el, rowIndex, colIndex, e, rec, rowEl) {
this.getStore('ListingStore').load();
},
handleDateSelect: function(gridview, el, rowIndex, colIndex, e, rec, rowEl) {
this.getStore('ListingStore').load({callback: function(response){
}});
This is a very complex case, so i am unable to post the entire code.
Thank You.
I think you have the issue described by me here:
http://www.sencha.com/forum/showthread.php?242445-Grid-filters-race-conditions-FiltersFeature
Regards,
Alek
Related
My store getting created in render function that one call get fired, but my requirement call should fired conditionally but store instance should create always.
For this requirement I am using following code for create store in render function,
Ext.create('mypage.store.customTreeGridStore', {
storeId: 'myStore',
proxy: {
type: 'rest',
startParam: undefined,
filterParam: undefined,
sortParam: undefined,
paramsAsJson: true,
limitParam: 'pageSize',
pageParam: 'pageNo',
restService: 'rest',
restOperation: 'getOperation',
url: me.urlparams,
autoLoad: true,
actionMethods: {
read: 'POST'
}
}
});
and I have added listener in store
beforeload: function(store, operation, eOpts) {
return booleanFlag;
}
When page is loading I could get beforeLoad boolean flag false and while page refreshing call is not getting fired but Store instance created successfully,
but I have text box where I am searching grid records. When I am searching any text in textbox I could not getting any record in grid.
But once booleanFlag is true I can search result in grid successfully . So what is the best way to resolve this issue?
Your store has autoLoad set to true, and to force the store to not load automatically all the time, you use the beforeload event to stop the autoLoad. Is this assessment correct?
How about, instead of
Ext.create('mypage.store.customTreeGridStore', {
proxy:{
autoLoad: true,
},
listeners:{
beforeload: function(store, operation, eOpts) {
return booleanFlag;
}
}
})
removing autoLoad and loading the store after creation only if required?
var store = Ext.create('mypage.store.customTreeGridStore', {
proxy:{
autoLoad: false,
}
});
if(booleanFlag) store.load();
I want to load a record based on my tree node selection and show it in my form. But my store is not loaded in my controller handler. Where and how should I load the store with my parameter?
var me = this;
var idTag= me.getMyNode();
me.getTagStore().on('beforeload', function(store, operation, eOpts) {
operation.params = {
idTag: idTag
};
}, me);
// it will not be loaded here and I get rec=undefined
var rec = me.getTagStore().load().getAt(0);
me.getMyForm().loadRecord(rec);
And here is my store:
Ext.define('TTT.store.Tag', {
extend: 'Ext.data.Store',
requires: [
'TTT.model.Tag'
],
model: 'TTT.model.Tag',
proxy: {
type: 'ajax',
url: 'tag/find.json',
reader: {
type: 'json',
root: 'data'
}
}
,baseParams: {
idTag: 30
},
});
You can call the load method manually whenever needed and pass any parameters needed, like this:
me.getTagStore().load({
params: {
idTag: idTag
}
});
When you call this you should see your request with the parameter in your console window in the browser.
In your code above, this line:
// it will not be loaded here and I get rec=undefined
var rec = me.getTagStore().load().getAt(0);
The load operation takes a little time, not much but it does take a little time. You need to listen to the load event on your store to be able to do things like this, here is an example:
me.getTagStore().load({
params: {
idTag: idTag
},
scope: this,
callback: function(records, operation, success) {
// the operation object
// contains all of the details of the load operation
console.log(records);
}
});
Checkout the documentation for store.
I have list and pull down to refresh plugin in it. When the refresh function fires i would like to show the load mask. But its not showing there. when i commented store.removeAll(); line i can see the loadmask working. I dont konw whats the problem with store.removeAll(). Please help me to solve this issue. Thanks in advance
{
xclass: 'Ext.ux.PullRefreshFn',
pullRefreshText: 'Pull down for refresh Contacts!',
refreshFn: function() {
console.log('pull refresh working');
Ext.Viewport.setMasked({
xtype: 'loadmask',
message: 'Please Wait...'
});
var store = Ext.getStore('Contactsstore');
store.removeAll();
var url = apiurl+'Contact.ashx?switch=GetContactList&api_id=4&getDataAgain=true';
store.getProxy().setUrl(url);
store.loadPage(1,{
callback: function (records, operation, success, response) {
if (success==1) {
Ext.Viewport.setMasked(false);
} else {
Ext.Viewport.setMasked(false);
}
}
});
Ext.getCmp('searchcontact').reset();
}
}
Here is my Store configuration
Ext.define('WinReo.store.Contactsstore', {
extend: 'Ext.data.TreeStore',
requires: [
'WinReo.model.Contactsmodel'
],
config: {
storeId: 'Contactsstore',
defaultRootProperty: 'items',
model: 'WinReo.model.Contactsmodel',
autoLoad: false,
pageSize: 20,
proxy: {
type: 'ajax',
method:'post',
id: 'Contactsstoreproxy',
url:apiurl+'Contact.ashx?switch=GetContactList&api_id=4&getDataAgain=false',
reader: {
type: 'json',
rootProperty: 'items'
}
},
listeners: {
load: function(store, records, successful, operation, eOpts) {
callback:{
succes:
if(store.getCount()!=0){
var RecordCount=store.getAt(0).get('RecordCount');
//console.log('RecordCount',RecordCount);
store.setTotalCount(RecordCount);
var storectscount = store.getTotalCount();
//Ext.Msg.alert('Store Total count',storectscount, Ext.emptyFn);
}
}
}
}
}
}
});
Loading masks won't get rendered until the browser has a chance to render them, and that won't happen until your Javascript code completes. I suspect that for some reason, the removeAll call isn't completing quickly (or at all), or an event listener on clear isn't completing like it needs to. Check your store's configuration for syncRemovedRecords: true and autoSync: true. You can also try removeAll(true) to keep the clear event from firing.
Update
Looking at your store definition, I can see at least one problem: Your load listener doesn't look like it's defined properly. You're defining a callback field inside of a function (which isn't going to compile), and 'succes' is misspelled. Is this what you had in mind?
load: function(store, records, successful, operation, eOpts) {
if(successful === true && store.getCount()!=0){
var RecordCount=store.getAt(0).get('RecordCount');
store.setTotalCount(RecordCount);
}
}
}
I want to filter an Ext store using a custom algorithm. The JSON/AJAX proxy returns >100 records and I need to reduce the number to the top-5 based on a number of criteria.
How to go about this (not the algorithm but where to trigger it)?
My current approach is to use a custom reader like so
Ext.define('MyReader', {
extend : 'Ext.data.reader.Json',
alias : 'reader.myReader',
getResponseData : function(response) {
var data = this.callParent([response]);
// algorithm
return filteredData;
}
});
Ext.define('SunApp.store.Stations', {
extend: 'Ext.data.Store',
requires: ['MyReader'],
config: {
model: 'SunApp.model.Station',
autoLoad: true,
proxy: {
type: 'ajax',
url: 'data.json',
reader: {
type: 'myReader'
}
}
}
});
but I'd much rather base the algorithm on the store model than on the raw JSON data. Hence, I'd like to filter while/after the data is loaded into the store. Note that the store is created implicitly by Ext when the list view is displayed:
Ext.define('SunApp.view.Stations', {
extend: 'Ext.List',
xtype: 'stations',
config: {
title: 'Stations',
store: 'Stations',
...
Therefore, I can't just add a function to the store that I invoke manually before it's being passed to the list.
In this case where the filter may need to traverse the store data (i.e. records) several times to reduce the full set to the desired set I believe (I'm still a Sencha rookie...) the following may be fine:
write an on-load event listener
do the magic filtering
call setData on the store passing the filtered data
Hence, instead of filtering in the reader it'd be like this:
Ext.define('SunApp.store.Stations', {
extend: 'Ext.data.Store',
config: {
model: ...,
sorters: [...],
listeners: {
load: function(store, records, success, eOpts) {
var filteredRecords = filter(records);
store.setData(filteredRecords);
}
},
proxy: ...
}
});
I am trying to build a search application using ExtJS. I have created dummy form to search for personal details. I have a php script connected to mysql DB. I am able to pass form parameters to php and able to get the return result in msg box. but I am not understanding how to pass it to store and display the same in grid in MVC. I have tried to pass the return data of php to store and then called Grid (List.js) in controller. still did not work. I have shown all the codes that i have used to do this.Another doubt which i have, is that essential to use proxy part of code (i.e url:app/scripts/Info.php) in both store and onSearchButtonClick function in controller? as I can directly pass the return values to store from onSearchButtonClick function, I hope it is not essential to connect php script in both places. However, it would be really nice experts clarify this.
Following is my store:
Ext.define('App.store.Info', {
extend: 'Ext.data.Store',
model: 'App.model.Info',
alias: 'widget.infostore',
pageSize : 50,
autoLoad : false,
remoteFilter: true,
proxy :{
type : 'ajax',
url : 'app/scripts/Info.php',
reader : {
type : 'json',
root : 'result',
successProperty : 'success'
}
},
listeners: {
load : function(store) {
store.each(function(record) {
record.commit();
});
}
}
});
My model looks perfect, simply to reduce somuch code I havent put here
Here is my grid:
Ext.define('App.view.info.List' ,{
extend: 'Ext.grid.Panel',
alias : 'widget.infolist',
store : 'Info',
initComponent: function(){
this.columns = [
{header:'PID',dataIndex:'pid'},
{header:'Name',dataIndex:'name'},
{header:'Address', dataIndex:'address'},
{header:'Contact', dataIndex:'contact'}
];
this.callParent(arguments);
}
});
This is what my php script returns:
{'success':true, 'result':{'pid':'100','name':'Suman','address':'Bangalore','contact':'suman#xyz.com'}}
Here is controller:
Ext.define('App.controller.Info', {
extend: 'App.controller.Base',
models: ['Info'],
stores: ['Info'],
views: [
'info.Index',
'info.List'
],
refs: [{ref: 'info',selector: 'info'}],
init: function(){
console.log('Main controller init');
this.control({
'button[action=search]':{
click: this.onSearchButtonClick
}
});
},
onSearchButtonClick:function(){
var form = Ext.getCmp('ppanel');
if(form.getForm().isValid()){
Ext.Ajax.request({
waitMsg: 'Searching...',
method: 'POST',
url: 'app/scripts/Info.php',
params: {
searchData: Ext.encode(form.getValues())
},
scope:this,
success: this.onSearchSuccess,
failure: this.onSearchFailure
//Ext.MessageBox.alert("XXXXX","dat");
});
}
},
onSearchSuccess: function(response){
var gData = Ext.JSON.decode(response.responseText);
//var grid = Ext.widget('infolist'); //not working -need help
this.getInfoStore().load(gData);
//Ext.getCmp().setActiveItem('infolist'); //not working-need help
//this.getViewport().getLayout().setActiveItem('infolist'); //not working need help
Ext.MessageBox.alert("XXXXX",response.responseText); //works
},
onSearchFailure: function(err){
Ext.MessageBox.alert('Status', 'Error occured during searching...');
}
});
I hope I have provided required information to understand the problem. Looking forward some sort of help.
The problem is that you have two instances of the store, one in grid and one in controller.
If you want a single instance store (like it seems you want) you have two options:
Add it to your application
Assign a storeId to your store definition.
(if you already added that store to your application, ignore the above text)
Or, better yet, do not work directly with the store but with your grid, like this:
First add a ref to your view->grid in your controller:
refs: [{ref: 'info',selector: 'info'},{selector:'infolist', ref:'infoGrid'}]
And then, in your onSearchSuccess handler, instead of calling: this.getInfoStore().load(gData); you should call: this.getInfoGrid().getStore().loadData(gData);
BTW: this.getInfoStore().load(gData); will never load an array of data or a record, for that you should use: this.getInfoStore().loadData(gData);
Hope this gets you in the right track.