Search code examples
javascriptdojoselectedindex

selectedindex resets to 0 after function end


I am struggling with a seemingly simple piece of javascript that performs a lookup to populate a select element. I store the current value in a variable, and once the script has performed its lookup and populated the select with the new list, I then look up the index of the previously selected value and select it. This all works fine, though once the function completes, the selectedindex is getting reset to 0 again.

function findCleaningFrequency(){
    var url = "${cleaningFrequencyLookup}".replace('SUBME', dojo.byId('ams.member').value);
    var listbox = dojo.byId('ams.cleaningFrequency');
    var selectedoption = listbox.selectedIndex;
    var selectedtext = listbox[selectedoption].text;
    dojo.xhrGet({
        url : decode(url),
        handleAs : 'json',
        node:  dojo.byId('ams.cleaningFrequency'),
        load : 
          function(responseObject, ioArgs){

            fillSelect(responseObject, ioArgs.args.node.id);
          }
      });
    for (var i = 0; i < listbox.options.length; ++i) {
        if (listbox.options[i].text === selectedtext ) listbox.options[i].selected = true;
    }
}

I can't see any reason for this, and I can step through it in a debugger and watch it working correctly (and selecting the correct option in the new list which is returned correctly) until it completes (it goes through the for loop at the end, correctly selecting the item as expected), and then the dropdown resets to 0 again! Out of interest, we are using an old version of dojo (1.0.2), and for the purposes of this, we can't upgrade just in case that works.


Solution

  • Without being able to see your specific site, it's hard to know for sure what the problem is.

    However, we can make a fair guess that you're seeing an artifact from the asynchronous nature of xhr. It's likely that your fillSelect() call is running /after/ your final loop. This is because xhr callbacks execute when the XHR returns, not immediately.

    Likely, the simple fix is to move the selectedtext loop into the callback, like so:

    load: function(responseObject, ioArgs){
        fillSelect(responseObject, ioArgs.args.node.id);
        for (var i = 0; i < ioArgs.args.node.options.length; ++i) {
            if (ioArgs.args.node.options[i].text === selectedtext ) ioArgs.args.node.options[i].selected = true;
        }
    }
    

    Separately, consider using the Javascript closure to access listbox directly in this callback, and increase readability:

    load: function(responseObject){
        fillSelect(responseObject, listbox.id);
        for (var i = 0; i < listbox.options.length; ++i) {
            if (listbox.options[i].text === selectedtext ) listbox.options[i].selected = true;
        }
    }