PDA

View Full Version : [solved] ComboBox state recovery



mfrancey
24 Feb 2011, 7:39 AM
Hi there,

I have a grid, working properly with filters and paging. I also added successfully a combobox to let the user choosing the number of records he wants to display per page. Everything works fine.

What I want to do is to retrieve the last state of the "record per page" combobox for allowing the user to recover from his last visit.
It seems that the "stateful: true" defined in the comboBox object is not working.
Of course, my var "recPerPage" need also to be dynamically redefined if the cookie exists.

Any idea ? Thanks for your help


Ext.onReady(function(){

Ext.QuickTips.init();

Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
// for this demo configure local and remote urls for demo purposes
var url = {
local: '/v2/_lab/grid-filtering/grid-filter.json', // static data file
remote: '/v2/_lab/grid-filtering/grid-filter.php'
};

// configure whether filter query is encoded or not (initially)
var encode = false;

// configure whether filtering is performed locally or remotely (initially)
var local = false;
var recPerPage = 25;
var store = new Ext.data.JsonStore({
// store configs
autoDestroy: true,
url: (local ? url.local : url.remote),
remoteSort: false,
sortInfo: {
field: 'company',
direction: 'ASC'
},
storeId: 'myStore',

// reader configs
idProperty: 'id',
root: 'data',
totalProperty: 'total',
fields: [{
name: 'id'
}, {
name: 'company'
}, {
name: 'price',
type: 'float'
}, {
name: 'date',
type: 'date',
dateFormat: 'Y-m-d H:i:s'
}, {
name: 'visible',
type: 'boolean'
}, {
name: 'size'
}]
});

var filters = new Ext.ux.grid.GridFilters({
// encode and local configuration options defined previously for easier reuse
encode: encode, // json encode the filter query
local: local, // defaults to false (remote filtering)
filters: [{
type: 'numeric',
dataIndex: 'id'
}, {
type: 'string',
dataIndex: 'company',
disabled: true
}, {
type: 'numeric',
dataIndex: 'price'
}, {
type: 'date',
dataIndex: 'date'
}, {
type: 'list',
dataIndex: 'size',
options: ['small', 'medium', 'large', 'extra large'],
phpMode: true
}, {
type: 'boolean',
dataIndex: 'visible'
}]
});

// use a factory method to reduce code while demonstrating
// that the GridFilter plugin may be configured with or without
// the filter types (the filters may be specified on the column model
var createColModel = function (finish, start) {

var columns = [{
dataIndex: 'id',
header: 'Id',
// instead of specifying filter config just specify filterable=true
// to use store's field's type property (if type property not
// explicitly specified in store config it will be 'auto' which
// GridFilters will assume to be 'StringFilter'
filterable: true
//,filter: {type: 'numeric'}
}, {
dataIndex: 'company',
header: 'Company',
id: 'company',
filter: {
type: 'string'
// specify disabled to disable the filter menu
//, disabled: true
}
}, {
dataIndex: 'price',
header: 'Price',
filter: {
//type: 'numeric' // specify type here or in store fields config
}
}, {
dataIndex: 'size',
header: 'Size',
filter: {
type: 'list',
options: ['small', 'medium', 'large', 'extra large']
//,phpMode: true
}
}, {
dataIndex: 'date',
header: 'Date',
renderer: Ext.util.Format.dateRenderer('m/d/Y'),
filter: {
//type: 'date' // specify type here or in store fields config
}
}, {
dataIndex: 'visible',
header: 'Visible',
filter: {
//type: 'boolean' // specify type here or in store fields config
}
}];

return new Ext.grid.ColumnModel({
columns: columns.slice(start || 0, finish),
defaults: {
sortable: true
}
});
};
var combo = new Ext.form.ComboBox({
id:'recPerPageCombo',
name : 'recPerPageCombo',
width: 40,
store: new Ext.data.ArrayStore({fields: ['id'], data : [['10'],['25'],['50'],['100'],['200'],['500']]}),
mode : 'local',
listWidth : 50,
triggerAction : 'all',
displayField : 'id',
valueField : 'id',
editable : false,
stateId: 'recPerPage',
stateful: true

});

var bbar = new Ext.PagingToolbar({
store: store,
pageSize: recPerPage,
displayInfo: true,
displayMsg: '{0} > {1} / Total: {2}',
plugins: [filters],
stateId:'gridbbar',
items:[ '-', combo, '/ page ' ]
});
combo.on('select', function(combo, record) {
bbar.pageSize = parseInt(record.get('id'), 10);
bbar.doLoad(bbar.cursor);
}, this);

var grid = new Ext.grid.GridPanel({
title: 'Array Grid',
// config options for stateful behavior
stateful: true,
stateId: 'mygrid',
collapsible:true,
maximizable: true,
resizable:true,
border: true,
store: store,
stripeRows: true,
width: Ext.getBody().getWidth()-270,
height:Ext.getBody().getHeight()-200,
colModel: createColModel(4),
loadMask: true,
plugins: [filters],
autoExpandColumn: 'company',
renderTo:'gridpanel_1',
listeners: {
render: {
fn: function(){
store.load({
params: {
start: 0,
limit: recPerPage
}
});
}
}
},
bbar: bbar
});


Ext.EventManager.onWindowResize(function(){
grid.setWidth(Ext.getBody().getWidth()-270); alert(combo.getValue());
});



});

Condor
24 Feb 2011, 7:46 AM
A combobox doesn't know how to keep state.

You'll also have to write getState and applyState methods and configure it with stateEvents:['change'] so it knows when the state changes.

mfrancey
24 Feb 2011, 7:56 AM
Thanks for your answer Condor.

I'm sure I'm not the first to have this kind of needs, but I didn't find any working example.

Do you have a working example of this kind of technique / implementation? I didn't find anything even after Googling for a while...

Thanks

Condor
24 Feb 2011, 8:05 AM
Haven't tested, but you could try:

stateful: true,
stateId: 'mycombobox',
stateEvents: ['select'],
getState: function(){
return {value: this.getValue()};
},
applyState: function(state) {
this.setValue(state.value);
}

mfrancey
24 Feb 2011, 2:14 PM
Great, it works like a charm... Thanks Condor !

Furthermore, I needed to add a default number of records pers page (for the first visit...):


var recPerPage = 25;Then define the value in the comboBox


var combo = new Ext.form.ComboBox({
id:'recPerPageCombo',
name : 'recPerPageCombo',
width: 40,
store: new Ext.data.ArrayStore({fields: ['id'], data:[['10'],['25'],['50'],['100']]}),
mode : 'local',
listWidth : 50,
triggerAction : 'all',
displayField : 'id',
valueField : 'id',
editable : false,
stateful: true,
value: recPerPage, // <<< here's the default value
stateId: 'mycombobox',
stateEvents: ['select'],
getState: function(){return {value: this.getValue()};},
applyState: function(state) {this.setValue(state.value);}

});And finally define the limit in the listener of the grid object for my JSON Request


var grid = new Ext.grid.GridPanel({
title: 'Array Grid',
...
...
listeners: {
render: {
fn: function(){
store.load({
params: {
start: 0,
limit: combo.value // <<< here's the limit
}
});
}
}
},
bbar: bbar
});

mfrancey
24 Feb 2011, 2:27 PM
... but I still have one problem.

When I change the number of records in my ComboBox, I'd like to always got to page 1.
Because for instance:

Let's say that I have a total number of 27 records, displaying 10 records per page (=3 pages). If I'm on page 2 and I change the number of records to 50 records per page, the paging displays page 2 of 1, which is confusing...

So my question: how to go to page 1 after changing the value of my comboBox?

mfrancey
24 Feb 2011, 2:49 PM
And the answer is:


combo.on('select', function(combo, record) {
bbar.pageSize = parseInt(record.get('id'), 10);
bbar.changePage(1);
}, this);

I like writing to myselft, hoping it'll help someone else :-)