Building a clearable combobox to allow users to sort Extjs grids

Here’s one strategy for setting up multiple filters for an extjs grid, and I can’t say if it’s the best or worst, but it works with minimal code.  Combo boxes are good, they limit what the user may sort on and could be employed to show a range of values that are already in the database, I like to connect them to a store that runs a Select Distinct whatever from some_table so that I get a quick view of what’s in the dataset as well as a way to sort the data. The only issue that I have come across when using several combo boxes for sorting is the fact that there is no real easy way for the user to clear the contents of the combo box, so in order to provide a clear function to all of my combo boxes that are specifically geared to grid sorting I set up the following solution.

1)      First you have to extend the Combobox to add a trigger that the user will push to clear the box and trigger the grid refresh. The image class for your second trigger is already in the resources/css/ext-all.css file that ships with extjs.

2)      You will notice in the code below that the first six characters of the id is getting parsed from the id to determine if they equal the string ‘search’. This is done to allow you to have clearable combo boxes in a form for example, where you want to allow the user to clear the contents but you do not want to allow type ahead – yes there may be some instances where this would come in handy.

3)      Finally, if the beginning of the id of the combo box is search we call the function performGridSort(); which will build a set of parameters based on the clearable combo boxes associated to the grid.

Ext.form.ClearableComboBox = Ext.extend(Ext.form.ComboBox, {
    initComponent : function(){
        Ext.form.ClearableComboBox.superclass.initComponent.call(this);
        this.triggerConfig = {
            tag:'span', cls:'x-form-twin-triggers', style:'padding-right:2px',
                 // padding needed to prevent IE from clipping 2nd trigger button
            cn:[
                {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger"},
                {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger x-form-clear-trigger"}
               ]
           };
    },
    getTrigger : function(index){
        return this.triggers[index];
    },
    initTrigger : function(){
        var ts = this.trigger.select('.x-form-trigger', true);
        this.wrap.setStyle('overflow', 'hidden');
        var triggerField = this;
        ts.each(function(t, all, index){
            t.hide = function(){
                var w = triggerField.wrap.getWidth();
                this.dom.style.display = 'none';
                triggerField.el.setWidth(w-triggerField.trigger.getWidth());
            };
            t.show = function(){
                var w = triggerField.wrap.getWidth();
                this.dom.style.display = '';
                triggerField.el.setWidth(w-triggerField.trigger.getWidth());
            };
            var triggerIndex = 'Trigger'+(index+1);
 
            if(this['hide'+triggerIndex]){
                t.dom.style.display = 'none';
            }
            t.on("click", this['on'+triggerIndex+'Click'], this, {preventDefault:true});
            t.addClassOnOver('x-form-trigger-over');
            t.addClassOnClick('x-form-trigger-click');
        }, this);
        this.triggers = ts.elements;
    },
    onTrigger1Click : function() {this.onTriggerClick()},
   // pass to original combobox trigger handler
    onTrigger2Click : function() {  
  // This is your new clear function
                    this.clearValue();
                    /* Clear the Customer Combobox */
                   test_value = this.getName().substring(0,6);
                   
                    if(test_value === 'search'){
                          performGridSort();
                      }
                }
});
 

And now the sort function:

function performGridSort(){
// Get all of the values from the drop down boxes etc..
var d  = Ext.getCmp('search_department’).getValue(); 
var r   = Ext.getCmp('search_region’).getValue();            
               
                               
your_store.reload({params:{department:d, region:r }});              
}

I know you could have used set base param but then the logic on the second trigger would actually contain more code.

Ever get an esoteric Extjs error that reads “syntax error line 4233” or “syntax error line 7″

Here’s a little information that may save someone somewhere a few hours. Ever get an esoteric Extjs error that reads “syntax error line 4233” in ext-all-debug (version 3.3.1 but has been confirmed to happen on earlier versions as well) or on line 7 if you have not already decided to add the –debug to the end of your ext include file. Turns out that ext is performing an eval on your code that is being returned from whatever page you called when you submitted the form, the exact source code is here:

doDecode = function(json){
                //alert(json);  //remove leading slashes to enable json debugging
            return eval("(" + json + ")");   
        },

Notice that there is a commented out alert, if you were to uncomment that alert you would then see your JSON strings in alert boxes every time that Ext returned one.

More often than not the error that you are experiencing is due to an extra or illegal character in the JSON.