Building a Reverse Lookup Dropdown Box for an ESRI Widget with Dojo

Aubrey Drescher
4 min readMay 12, 2022
Photo by Kelly Sikkema on Unsplash

Some time ago, I was asked to make a new widget for our ArcGIS Web AppBuilder application. The only requirements I was given for the widget were:

“We are transitioning to a new naming convention for our map layers. Here is a list of old and new layer names. We want people to be able to search for a layer and see its new name.”

I started thinking about how this would work, and I decided to use an autocomplete drop down box. An autocomplete drop down box is one where you start typing and it narrows down your options as you go.

It’s also called a typeahead.

There’s many ways I could have built this, using JQuery or Bootstrap, but I decided to do it the Dojo way.

Dojo is a JavaScript framework and it’s the fundamental building block of the ArcGIS API for JavaScript. The ArcGIS API for JavaScript, in turn, is the fundamental building block for the ArcGIS Web AppBuilder. So you could say Dojo is at the bottom of the technology pyramid — it’s what everything is made of.

Dojo isn’t the easiest language to write in. It isn’t widely used or well documented, and there’s a lot of overhead (extra steps you have to take in order to get anything started in it). But I think it is best to be consistent and use the same language throughout the application whenever possible. I have looked at the code that our ESRI contractors have written for us, and they also do everything the Dojo way.

So I made an autocomplete drop down box using a Dojo ComboBox that is populated by a Dojo Memory Store and filtered by a Dojo Filter Expression.

This combo box lets people type ahead to pick an old layer name.
this.geoInput = new dijit.form.ComboBox({
id: "geonetwork",
store: new Memory({ data: geonetwork, idProperty: "name" }),
autoComplete: false,
queryExpr: "*${0}*",
intermediateChanges: true,
placeHolder: "Select an item or start typing",
query: {fclass: /.*/},
style: "width: 360px; height: 24px;",
required: false,
searchAttr: "name",
labelAttr: "label",
labelType: "html",
}, "geonetwork").placeAt(this.geoInput);

Then, I use Dojo Filtering Select boxes to display for them the new layer name that is associated with the old layer name that they selected.

this.fclassInput = new dijit.form.FilteringSelect({
id: "utilclass",
store: new Memory({ idProperty: "name", data: utilclass }),
autoComplete: false,
hasDownArrow: false,
readOnly: true,
required: false,
style: "width: 360px;",
}, "utilclass").placeAt(this.fclassInput);

Things got complicated when I showed my initial design and they came back with a new requirement:

“Can you make it have a reverse lookup? We want people to be able to search for a new layer name and see what it used to be called!”

This was hard to do because Dojo Filtering Selects don’t work that way — Dojo expects a chain of dependency where the primary box has its value controlled by the user, and the secondary box has its value controlled by the primary box. Now I needed to make it so both boxes are equals in the hierarchy, and they both can be changed by each other.

I did this by configuring both boxes as the primary box (the one changed by the user) and then writing some custom code that runs on the onChange event.

//If the value is changed by another box instead of by the user, get the selected item out of the memory storeonChange: function(selectedValue){
if (!this.item) {
var selectedItem = this.store.get(selectedValue)
if (selectedItem) {
this.item = selectedItem;
} else {
return;
}
}
dijit.byId('geonetwork').set('value', this.item ?
this.item.geo : null);
document.getElementById("geo_symbol").src = this.item ?
iconpath + this.item.symbol : null;
}

If the value is changed by the user, it will work as designed without the custom code. But if the value is changed by the other box, the custom code takes over and finds a match in the memory store.

This is a lot of behind the scenes effort that my familiarity with Dojo helped me to be able to pull off. I spent about two years during my previous job working straight with the ArcGIS API for JavaScript without the Web AppBuilder as an extra layer of abstraction on top of it. It forced me to get more in to the weeds with Dojo and be able to customize more things. I hope that this tutorial will give you a jump start to be able to do the same.

--

--