Fun with Dojo filtering selects

While the Dojo JavaScript libraries are really an excellent resource for building rich internet applications (RIAs), sometimes Dojo just makes things harder than they have to be.  Last week I was working on public map viewer, based on our custom implementation of ESRI's JavaScript API starter kit,  for one of our clients.  The site is really pretty basic in terms of functionality with one of the tools allowing the user to configure and execute a multi-criteria search for information and have that information displayed on a map.  The user interface looks something like the following screen cap:

Media_httpbriannoylef_zdezh

In this user interface example, the combo boxes for counties and cities are Dojo FilteringSelect controls.  The FilteringSelect extends the typical html drop down so that you get an intellisense/autocomplete of sorts when the user starts typing in the combo box.  In addition, in the event that the user types a value rather than using the drop down list, the FilteringSelect will validate manual text entries to ensure they are in the select list.  All of this prevalidation is important because it allows us to reduce the potential for errors in searches by constraining the user's input to a list of valid values pulled from database lookup tables.  It's a pretty neat little control...until you have to clear it.

The issue:

There are basically two possible scenarios where we need to clear information from a Dojo FilteringSelect on our search form in this example.  The first is obviously when the user clicks the Clear button to clear the search form and start over.  The second case is when we need to reload and reset the data driving the city FilteringSelect box if the user makes or changes a county selection in the county FilteringSelect box. 

The user click of the Clear button to clear all search form values is sufficient to illustrate the issue so I'll expand on that a bit.  The wiring for events like the typical "onClick" for a button in Dojo is extremely simple:

     this.connects.push(dojo.connect(this.widgets.clearLocateButton, "onClick",

     this, "onClearLocateButtonClick"));

Breifly, the line of code shown above uses dojo.connect() to assign a function called onClearLocateButtonClick to be the event handler for the click event of a button on our widget with an ID of clearLocateButton.  The onClearLocateButtonClick function is equally straightforward, simply clearing any user entered values from the input boxes on the widget.

    //--------------------------------------------
    // Handle event raised when user clicks the Clear
    // button on the Address UI. Resets user input
    // controls.
    //--------------------------------------------
    onClearLocateButtonClick: function(evt) {
        try {
            // reset user inputs
            this.widgets.countyComboBox.reset();
            this.widgets.propertyTextBox.reset();
            this.widgets.addressTextBox.reset();
            this.widgets.cityComboBox.reset();
            this.loadCityLookup();

        }
        catch (err) {
            console.error("Error clearing address information", err);
        }
    }

Each input control in the widget receives a reset call which is supposed to clear any entered value for the control.  The problem?  Let's say a user has selected County = Larimer and City= Fort Collins in the above UI.  Clicking the clear button resets all widget controls to empty as expected however the county and city FilteringSelect controls will end up having validation errors displayed. 

Media_httpbriannoylef_lkrku

But there is no validation error because the user consciously asked for all the information to be cleared.  None of the fields is required so the validation error shouldn't be there. 

The solution:

After a variety of configuration changes, at least three Google searches and some hair pulling, I did arrive at the following solution to get rid of the validation errors when FilteringSelects are cleared using the reset method.  The solution is basically to change the way we reset the values in a filtering select box within our onClearLocateButtonClick event handler.

    //--------------------------------------------
    // Handle event raised when user clicks the Clear
    // button on the Address UI. Resets user input
    // controls.
    //--------------------------------------------
    onClearLocateButtonClick: function(evt) {
        try {
            // reset user inputs
            this.widgets.propertyTextBox.reset();
            this.widgets.addressTextBox.reset();
           //need to manually reset the city and county boxes for some reason
            this.widgets.countyComboBox._hasBeenBlurred=false;
            this.widgets.countyComboBox.attr('displayedValue', '');           
            this.widgets.cityComboBox._hasBeenBlurred = false;
            this.widgets.cityComboBox.setDisplayedValue('');
            this.loadCityLookup();

        }
        catch (err) {
            console.error("Error clearing address information", err);
        }
    }

I actually dug in to the API documentation and found that the setting the _hasBeenBlurred property to false and then manually setting the value of the control solves the issue.  Presto!  The offending validation error is gone from our widget when the user clears the search parameters.  Note the example code uses both the .attr() method and the .setDisplayedValue method simply as an example of two ways to accomplish the task.  I would note however that setDisplayedValue has been deprecated and will be removed from the Dojo API at version 2.

Now, I'm relatively new to the world of Dojo so this may or may not be the preferred method of tackling this issue. The use of _hasBeenBlurred is a bit of a code smell from my perspective because the '_' indicates a method that is supposed to be private.  However, sometimes we wind up trapped between doing things the absolutely right way and absolutely getting something done.  In this case I chose the latter.