-
3 Mar 2013 3:24 PM #1
4.2 ComboBox Query Enhancements
4.2 ComboBox Query Enhancements
First, please add config options to combobox for anyMatch and caseSensitive, which are passed to the stored queryFilter.
Second, please add code to the top of doQuery for:
Because when using field validation (allowBlank: false, forceSelection: true, typeAhead: true), and deleting values typed into the combo box, the full list does not appear (basically forceAll isn't being forced to true).Code:if( queryString.length < this.minChars ) { forceAll = true; }
Thanks,
Brian
-
3 Mar 2013 10:42 PM #2
Good ideas. The 4.2.0 release is frozen, but I'll add a ticket.
-
3 Mar 2013 11:35 PM #3
I think what you need to provide the expected user experience is below. Let me know if that works for you.
Code:Ext.override(Ext.form.field.ComboBox, { 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'; if (me.fireEvent('beforequery', qe) === false || qe.cancel) { return false; } // get back out possibly modified values queryString = qe.query; forceAll = qe.forceAll; // Re-filter if forceAll being passed // or query string is at least the required length // or dropdown is visible and the user will expect feedback - eg erasing and widening the query. if (forceAll || (queryString.length >= me.minChars) || (me.picker && me.picker.isVisible())) { // 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) { // Querying by a typed string... if (queryString || !forceAll) { // Ensure queryFilter is enabled and set the new value me.queryFilter.disabled = false; me.queryFilter.setValue(me.enableRegEx ? new RegExp(queryString) : queryString); } // Disable query value filter if no query string or forceAll passed else { me.queryFilter.disabled = true; } // Filter the Store according to the updated filter store.filter(); } 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; } });Search the forum: http://www.google.com/coop/cse?cx=01...%3Az7of1ufqccu
Read the docs too: http://extjs.com/deploy/dev/docs/
Scope: http://extjs.com/forum/showthread.ph...642#post257642
-
4 Mar 2013 2:31 AM #4
My understanding of minChars is that it's to be used with very large, remote datasets where a short query is too small to meaningfully filter the results set. It kind of defeats the purpose if the user can just delete their way around it.
Could a beforequery listener not be used to achieve the desired effect without any modifications to combobox itself?
-
4 Mar 2013 2:47 AM #5
That's true.
But for local datasets, it's intuitive that the query widens as you erase.
Perhaps the fix should be
Code:if (forceAll || (queryString.length >= me.minChars) || (isLocalMode && me.picker && me.picker.isVisible())) {Search the forum: http://www.google.com/coop/cse?cx=01...%3Az7of1ufqccu
Read the docs too: http://extjs.com/deploy/dev/docs/
Scope: http://extjs.com/forum/showthread.ph...642#post257642
-
4 Mar 2013 6:07 AM #6
Sounds right as a more general solution. For me, I've got a custom AnyMatchComboBox that I use only for local data sets. So for simplicity, I just have this (I'm using CoffeeScript):
Code:config: anyMatch: true caseSensitive: false initComponent: -> @callParent( [ arguments ] ) @queryFilter.anyMatch = @anyMatch @queryFilter.caseSensitive = @caseSensitive doQuery: ( queryString="", forceAll, rawQuery ) -> forceAll = true if queryString.length < @minChars @callParent( queryString, forceAll, rawQuery ) return true
-
4 Mar 2013 6:47 AM #7
I'm not sure it's intuitive for minChars to behave differently for local and remote data. Personally I think it would make more sense for the picker to be automatically hidden if the number of characters drops below minChars, though that would be a change of long-established behaviour.
In my opinion the main change that is required is to split up the monolith of doQuery to give a few nice template methods for hooking in these kinds of customizations. I've lost count of the number of times that I've seen someone have to copy and paste that whole crazy method just to make a tiny change for their specific use-case.
A few overridable methods and a bit of documentation and everything would be super-flexible without adding a load of new config options. The documentation here is key, e.g. the existing beforequery event is massively powerful but very few people understand how to use it.
-
4 Mar 2013 7:09 AM #8
Yes, breaking that up so that it could be operated by template methods would be a great solution to this one.
Configuring the Filter with matchAny and caseSensitive is done. I will look at breaking that method up to allow finer control.Search the forum: http://www.google.com/coop/cse?cx=01...%3Az7of1ufqccu
Read the docs too: http://extjs.com/deploy/dev/docs/
Scope: http://extjs.com/forum/showthread.ph...642#post257642
-
4 Mar 2013 7:58 AM #9
How's this for an idea?
The top of doQuery is simply:
After that, it continues with the test for previously cached queryString, and the bifurcation for isLocalMode/non-local.Code:// Decide if, and how we are going to query the store queryPlan = me.beforeQuery(queryString, forceAll, rawQuery); if (queryPlan === false || queryPlan.cancel) { return false; }
That queryPlan is that object containing the queryString, cancel flag, the forceAll flag.
So the beforeQuery method can be overridden. The base implementation does the default:
And a bit more documentation, and perhaps some examplage.Code:beforeQuery: function(queryString, forceAll, rawQuery) { var me = this, queryPlan = { query: queryString, forceAll: forceAll, combo: me, cancel: false }; if (me.fireEvent('beforequery', queryPlan) !== false) { if (!queryPlan.cancel && (queryPlan.forceAll || (queryPlan.queryString.length >= me.minChars))) { return queryPlan; } } return false; },Search the forum: http://www.google.com/coop/cse?cx=01...%3Az7of1ufqccu
Read the docs too: http://extjs.com/deploy/dev/docs/
Scope: http://extjs.com/forum/showthread.ph...642#post257642
-
4 Mar 2013 8:10 AM #10
Actually, better would be
So that override can always rely on a plan returning with the information in it rather than false.Code:beforeQuery: function(queryString, forceAll, rawQuery) { var me = this, queryPlan = { query: queryString, forceAll: forceAll, combo: me, cancel: false }; // Allow beforequery event to veto by returning false if (me.fireEvent('beforequery', queryPlan) == false) { queryPlan.cancel = true; } // Allow beforequery event to veto by returning setting the cancel flag else if (!queryPlan.cancel) { // If the minChars threshold has not been met, and we're not forcing an "all" query, cancel the query if (queryPlan.query.length < me.minChars && !queryPlan.forceAll) { queryPlan.cancel = true; } } return queryPlan; },
They may still want to overrule any cancel flag and manipulate the plan.Search the forum: http://www.google.com/coop/cse?cx=01...%3Az7of1ufqccu
Read the docs too: http://extjs.com/deploy/dev/docs/
Scope: http://extjs.com/forum/showthread.ph...642#post257642
Success! Looks like we've fixed this one. According to our records the fix was applied for
EXTJSIV-8947
in
4.2.1.


Reply With Quote
