PDA

View Full Version : Ext.ux.grid.filter.ListFilter -> loaded store



tobiu
31 Mar 2009, 12:21 AM
hi together,

i changed this file a bit.
in my case, i want to use a store for listFilter, that is already loaded.
in the original version, the menu is only created, if the config loadOnShow is set to true or if the store is loaded after creation of the gridFilters.

for config-stores, i love the combination of json-stores with a server-side generated data-config. the reason is, that the data is needed for sure at the initialisation of the site / system, but probably will change later. so, you dont need the first ajax-call. example with php:



bT.dataStores.roleStore = new Ext.data.JsonStore({
id : 'i'
,root : 'data'
,url : 'ajaxHandler/files/roleStore.php'
,data : <?require_once('ajaxHandler/files/roleStore.php');?>
,fields: [
{name: 'id' ,mapping: 'i'}
,{name: 'name' ,mapping: 'n'}
]
});


so, this store could be used for one (or more) comboBox and one (or more) gridFilterLists.
the problem is, that the onLoad event of the store might fire, before(!) the grid containing filters is created. so the menu might not be build.

so, here is the fix:



Ext.ux.grid.filter.ListFilter = Ext.extend(Ext.ux.grid.filter.Filter, {
labelField: 'text',
loadingText: 'Loading...',
loadOnShow: true,
value: [],
loaded: false,
phpMode: false,

init: function(){
this.menu.add('<span class="loading-indicator">' + this.loadingText + '</span>');

if(this.store){
if(this.loadOnShow){
this.menu.on('show', this.onMenuLoad, this);
} else {
if(this.loaded){
this.onLoad(this.store, this.store.data.items);
}
}

} else if(this.options){
var options = [];
for(var i=0, len=this.options.length; i<len; i++){
var value = this.options[i];
switch(Ext.type(value)){
case 'array': options.push(value); break;
case 'object': options.push([value.id, value[this.labelField]]); break;
case 'string': options.push([value, value]); break;
}
}

this.store = new Ext.data.Store({
reader: new Ext.data.ArrayReader({id: 0}, ['id', this.labelField])
});
this.options = options;

this.menu.on('show', this.onMenuLoad, this);
}
this.store.on('load', this.onLoad, this);

this.bindShowAdapter();
},

/**
* Lists will initially show a 'loading' item while the data is retrieved from the store. In some cases the
* loaded data will result in a list that goes off the screen to the right (as placement calculations were done
* with the loading item). This adaptor will allow show to be called with no arguments to show with the previous
* arguments and thusly recalculate the width and potentially hang the menu from the left.
*
*/
bindShowAdapter: function(){
var oShow = this.menu.show;
var lastArgs = null;
this.menu.show = function(){
if(arguments.length == 0){
oShow.apply(this, lastArgs);
} else {
lastArgs = arguments;
oShow.apply(this, arguments);
}
};
},

onMenuLoad: function(){
if(!this.loaded){
if(this.options)
this.store.loadData(this.options);
else
this.store.load();
}
},

onLoad: function(store, records){
var visible = this.menu.isVisible();
this.menu.hide(false);

this.menu.removeAll();

var gid = this.single ? Ext.id() : null;
for(var i=0, len=records.length; i<len; i++){
var item = new Ext.menu.CheckItem({
text: records[i].get(this.labelField),
group: gid,
checked: this.value.indexOf(records[i].id) > -1,
hideOnClick: false});

item.itemId = records[i].id;
item.on('checkchange', this.checkChange, this);

this.menu.add(item);
}

this.setActive(this.isActivatable());
this.loaded = true;

if(visible)
this.menu.show(); //Adaptor will re-invoke with previous arguments
},

checkChange: function(item, checked){
var value = [];
this.menu.items.each(function(item){
if(item.checked)
value.push(item.itemId);
},this);
this.value = value;

this.setActive(this.isActivatable());
this.fireEvent("update", this);
},

isActivatable: function(){
return this.value.length > 0;
},

setValue: function(value){
var value = this.value = [].concat(value);

if(this.loaded)
this.menu.items.each(function(item){
item.setChecked(false, true);
for(var i=0, len=value.length; i<len; i++)
if(item.itemId == value[i])
item.setChecked(true, true);
}, this);

this.fireEvent("update", this);
},

getValue: function(){
return this.value;
},

serialize: function(){
var args = {type: 'list', value: this.phpMode ? this.value.join(',') : this.value};
this.fireEvent('serialize', args, this);
return args;
},

validateRecord: function(record){
return this.getValue().indexOf(record.get(this.dataIndex)) > -1;
}
});


example-usage:



var gF = new Ext.ux.grid.GridFilters({
filters:[
{dataIndex: 'created', type: 'date'}
,{dataIndex: 'locationName', type: 'list', store: bT.dataStores.roleStore, loaded:true}
]
});



i hope this helps someone!


kind regards,
tobiu

mystix
31 Mar 2009, 1:16 AM
i think you've got an extra closing parenthesis in there..

tobiu
31 Mar 2009, 2:23 AM
hi mystix,

the parenthesis should be fine, but spaces and tabs where not shown very good in the original posting. i should become clearer now ;)


kind regards, tobiu