DOJO Advanced problems and solutions



ComboBox or FilteringSelect

Blank or clear field

To clear out the field in a FilteringSelect, take away the store, and reset the control
var tmp = myFilteringSelect.store;
myFilteringSelect.store = null;
myFilteringSelect.reset();
myFilteringSelect.store = tmp;

Listen for when a FilteringSelect has finished getting data from the store

var myListener = dojo.connect(myFilteringSelect,"_callbackSetLabel",dojo.hitch(this,function(){/*Note, by the nature of the code behind dojo.connect(), the _callbackSetLabel has finished it's thing before getting here, but more things may happen afterward that you are too early to stop, such as popups*/}));
or
var myListener = dojo.connect(myFilteringSelecte,"_setDisplayedValueAttr",dojo.hitch(this,function(){/*Same note as above*/}));
Note: The _setDisplayValueAttr gets called once the store is complete, since the FilteringSelect tries to fill in the display with the first returned record, however, _setDisplayValueAttr also gets called for other reasons so you should only listen to these locations for a short time after triggering the store to change or update. See code example below.

Stop a popup/dropdown/drop down box for any widget that mixes in dijit._HasDropDown.js

var myListener=dojo.connect(myFilteringSelect,"openDropDown",dojo.hitch(this.myFilteringSelect,function(){this.closeDropDown();}));
Be sure to disconnect your listener when complete or you will never get the dropdown to work again :(

Not so advanced question How to set the value of a FilteringSelect box based on the text value someone would enter

myFilteringSelect.set("displayedValue",newValue);

Example of a 3 key record selection where javascript must set a company code, an entry type, then wait for a date list to populate, then set that FilteringSelect list as well

loadPage: function(company, category, transactionDate){
       /*Situation: 
        *Screen has 2 independent FilteringSelects, a Company List and a Category List
        *The screen also has 1 dependent FilteringSelect, it lists transaction dates for a particular company and category
        *Some program wants this screen filled, rather than having the user choose the company, category, and transaction date, maybe it is a fancy lookup widget, or maybe the screen was launched and needs to be pre-populated from the launcher.
        *The transactionDate store is using a dojox.data.QueryReadStore so the local copy of the entire store is not resident in memory.
        *Goal:
        *Fill in the company, category, and transaction FiltingSelect boxes, then fill in the rest of the screen using loadCurrentPage() where loadCurrentPage uses the values in the company/category/transaction date fields.
        *Problem:
        *The transaction date store does not yet know what to request from the backend, and when it does, it is going to do it asynchronously and pre-select the first entry, if we set our value before-hand, we will loose our entry for the first returned entry.
        *Solution:
        *Set the first 2 FilteringSelects, set the query for the transaction date FilteringSelect, force the store to react by doing a reset() on the FilteringSelect
        *Wait for it to respond, then allow it to finish, then set the value.
        **/
       this.clearPage(); /*Clear the current page, so that, if we fail, we don't leave mixed information. It would not be good for the key fields to show one thing and the rest of the page to show something else.*/
       this.currentComp = company;
       this.currentCategory = category;
       this.currentTransDate = transactionDate;
       /*Set the company code Filtering Select to the appropriate company*/
       this.compCode.set("displayedValue",company);
       /*Set the category code FilteringSelect to the appropriate category*/
       this.categoryCode.set("displayedValue",category);
       /*If a listener is left over from a previous attempt, remove it*/
       if (this.transCodeRefreshListener!=null)dojo.disconnect(this.transCodeRefreshListener);       
       /*Set up listener to wait for the store request to occur when this.transDate.reset() happens. Once the store request happens, FilteringSelect calls _setDisplayValueAttr to set the value. After that we do our stuff*/
       var _this = this;
       this.transCodeRefreshListener = dojo.connect(this.transDate,"_setDisplayedValueAttr",dojo.hitch(_this,_this._loadPage_transDateLoaded_part1));
       this.transCodeRefreshStartTime = new Date().getTime();
       /*Set query so the store will request the transaction dates for this customer/category*/
       this.transDate.query = {"company": company, "category": category};
       this.transDate.set("disabled",""); /*Enable the transaction date box (I have it disabled when either compCode or categoryCode are not valid)*/
       /*tell the FilteringSelect to carry out the store request*/
       this.transDate.reset();
   },
   
   _loadPage_transDateLoaded_part1: function(){
       var nextStep=false;
       /*If more than a second went by, there may have been a problem loading the page and the current call to _setDisplayedValueAttr may have nothing to do with us so give up :(*/
       if (new Date().getTime() - this.transCodeRefreshStartTime<1000)nextStep=true;
       /*Disconnect the listener, since, for good or bad, we are done listening until the next time someone calls loadPage(...)*/
       if (this.transCodeRefreshListener!=null)dojo.disconnect(this.transCodeRefreshListener);
       this.transCodeRefreshListener = null;
       this.transCodeRefreshStartTime=0;
       /*Give the thread back to the FilteringSelect to finish it's work, the time is not important, the act of temporarilly letting go of the process thread is.*/
       var _this = this;
       if(nextStep)setTimeout(dojo.hitch(_this,_this._loadPage_transDateLoaded_part2),1);
   },
   
   _loadPage_transDateLoaded_part2: function(){
       /*We want to verify success so lets listen again, but we don't want to listen to _setDisplayedValueAttr() because that is just us doing the request and it is going to verify our value asynchronously so we will be premature and only see what we want, not what we need. However, that asynchronous call is going to call _callbackSetLabel when verification is complete.*/
       this.transCodeRefreshListener = dojo.connect(this.transDate,"_callbackSetLabel",dojo.hitch(_this,_this._loadPage_transDateLoaded_part3));
       this.transCodeRefreshStartTime = new Date().getTime();
       /*We should now be able to set the date.*/
       this.transDate.set("displayedValue",this.currentTransDate);
   },
   
   _loadPage_transDateLoaded_part3: function(){
       var nextStep=false;
       /*If more than a second went by, there may have been a problem loading the page and the current call to _callbackSetLabel may have nothing to do with us so give up (again), if a second seems too short, you could wait two or three seconds, but don't wait too long or the user may change the screen selection and this stuff becomes invalid but you react to it anyway, that being said, this wasn't the important place to give up since we aren't doing anything else to the keys, where as the earlier routine was more important because we force the transDate field to change, and if the user was already re-selecting various keys, we would want to stop what we are doing.*/
       if (new Date().getTime() - this.transCodeRefreshStartTime<1000)nextStep=true;
       if (this.transCodeRefreshListener!=null)dojo.disconnect(this.transCodeRefreshListener);
       this.transCodeRefreshListener = null;
       this.transCodeRefreshStartTime=0;
       /*Give the thread back to the FilteringSelect to finish it's work (again).*/
       var _this = this;
       if(nextStep)setTimeout(dojo.hitch(_this,_this._loadPage_transDateLoaded_part4),1);
   },
   
   _loadPage_transDateLoaded_part4: function(){
       /*If were are here, the 3 boxes should be stable, let us see whether they have the correct values*/
       if (this.compCode.get("value")==this.currentComp && this.categoryCode.get("value")==this.currentCategory && this.transDate.get("value")==this.currentTransDate){
           /*Yea! the keys are correctly set, lets load the rest of the page. If any of the above failed, we would have given up and left the rest of the page alone.*/
           this.loadCurrentPage();
       }
   },
   
   loadCurrentPage: function(){
       /*TODO: write routine to load data entry or inquiry screen for selected multi-key record*/
   },





Lee Lofgren
Last Modified 07/20/2011