PDA

View Full Version : [CLOSED] Filter SelectBox before expanding it



RCN
Mar 28, 2014, 6:36 PM
Hi, i would like to know how to filter the items of a SelectBox before expanding it.

On the following example, please, press Filter button and then, expand the SelectBox. Note the items were not filtered as expected.
9011

Now, please refresh the page, then expand the SelectBox, then press Filter button and then, expand the SelectBox once again.
9021

Any ideas to overcome this issue?

Thanks in advance.



<!DOCTYPE html>
<html>
<head id="Head1" runat="server">
<script type="text/javascript">
var filter = function () {
var arr = new Array("1", "2");
App.SelectBox1.store.filterBy(function (enumeracao) {
return Ext.Array.contains(arr, enumeracao.data[App.SelectBox1.valueField]);
});
}
</script>
</head>
<body>
<ext:ResourceManager runat="server" />
<ext:Button Text="Filter" runat="server">
<Listeners>
<Click Handler="filter();" />
</Listeners>
</ext:Button>
<ext:SelectBox ID="SelectBox1" runat="server">
<Items>
<ext:ListItem Text="Ext" Value="1" />
<ext:ListItem Text="Net" Value="2" />
<ext:ListItem Text="Ext.Net" Value="3" />
</Items>
</ext:SelectBox>
</body>
</html>

Daniil
Mar 29, 2014, 12:06 AM
Hi Raphael,

Yes, first expand clears any filtration. You can apply your own filter within a ComboBox's Expand listener.

RCN
Mar 31, 2014, 2:19 PM
It's possible to overcome the issue presented above by setting SelectBox's lasQuery property to "" (line 7).



<!DOCTYPE html>
<html>
<head id="Head1" runat="server">
<script type="text/javascript">
var filter = function () {

App.SelectBox1.lastQuery = "";

var arr = new Array("1", "2");
App.SelectBox1.store.filterBy(function (enumeracao) {
return Ext.Array.contains(arr, enumeracao.data[App.SelectBox1.valueField]);
});
}
</script>
</head>
<body>
<ext:ResourceManager runat="server" />
<ext:Button ID="Button3" Text="Filter" runat="server">
<Listeners>
<Click Handler="filter();" />
</Listeners>
</ext:Button>
<ext:SelectBox ID="SelectBox1" runat="server">
<Items>
<ext:ListItem Text="Ext" Value="1" />
<ext:ListItem Text="Net" Value="2" />
<ext:ListItem Text="Ext.Net" Value="3" />
</Items>
</ext:SelectBox>
</body>
</html>


The solution presented above works because:

At line 37 of ComboBox's doQuery method, the filter will be cleared only when the ComboBox's lastQuery is different of the current queryString.



doQuery: function(queryString, forceAll, rawQuery) {
queryString = queryString || '';

// store in object and pass by reference in 'beforequery'
// so that client code can modify values.
var me = this,
qe = {
query: queryString,
forceAll: forceAll,
combo: me,
cancel: false
},
store = me.store,
isLocalMode = me.queryMode === 'local',
needsRefresh;

if (me.fireEvent('beforequery', qe) === false || qe.cancel) {
return false;
}

// get back out possibly modified values
queryString = qe.query;
forceAll = qe.forceAll;

// query permitted to run
if (forceAll || (queryString.length >= me.minChars)) {
// expand before starting query so LoadMask can position itself correctly
me.expand();

// make sure they aren't querying the same thing
if (!me.queryCaching || me.lastQuery !== queryString) {
me.lastQuery = queryString;

if (isLocalMode) {
// forceAll means no filtering - show whole dataset.
store.suspendEvents();
needsRefresh = me.clearFilter();
if (queryString || !forceAll) {
me.activeFilter = new Ext.util.Filter({
root: 'data',
property: me.displayField,
value: me.enableRegEx ? new RegExp(queryString) : queryString
});
store.filter(me.activeFilter);
needsRefresh = true;
} else {
delete me.activeFilter;
}
store.resumeEvents();
if (me.rendered && needsRefresh) {
me.getPicker().refresh();
}
} else {
// Set flag for onLoad handling to know how the Store was loaded
me.rawQuery = rawQuery;

// In queryMode: 'remote', we assume Store filters are added by the developer as remote filters,
// and these are automatically passed as params with every load call, so we do *not* call clearFilter.
if (me.pageSize) {
// if we're paging, we've changed the query so start at page 1.
me.loadPage(1);
} else {
store.load({
params: me.getParams(queryString)
});
}
}
}

// Clear current selection if it does not match the current value in the field
if (me.getRawValue() !== me.getDisplayValue()) {
me.ignoreSelection++;
me.picker.getSelectionModel().deselectAll();
me.ignoreSelection--;
}

if (isLocalMode) {
me.doAutoSelect();
}
if (me.typeAhead) {
me.doTypeAhead();
}
}
return true;
},

/**
* Clears any previous filters applied by the combo to the store
* @private
* @return {Boolean} True if a filter was removed
*/
clearFilter: function() {
var store = this.store,
filter = this.activeFilter,
filters = store.filters,
remaining;

if (filter) {
if (filters.getCount() > 1) {
// More than 1 existing filter
filters.remove(filter);
remaining = filters.getRange();
}
store.clearFilter(true);
if (remaining) {
store.filter(remaining);
}
}
return !!filter;
}

RCN
Mar 31, 2014, 2:28 PM
Daniil, what do you think about the solution presented above?

Daniil
Apr 01, 2014, 2:46 AM
I cannot forecast all possible scenarios, but nothing criminal, at least. I would say it is an appropriate solution for your case.

RCN
Apr 01, 2014, 12:40 PM
Thank you Daniiil. Please mark this thread as closed.

Daniil
May 26, 2014, 7:03 AM
Here is a similar request with a ComboBox.
http://forums.ext.net/showthread.php?35631

It looks a Store's addFilter works well. Maybe, it is good enough for a SelectBox as well.

RCN
May 26, 2014, 12:29 PM
Thank you Daniil