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

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.

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Handle arbitrary JSON in golang

Day 42 | 100 Days Full-Stack Challenge

Life Without jQuery

Dynamic sidebar menu inAngular

Why I Don’t Use Async/Await

JS Philosophy 1

Design Patterns to build UI Components library in React

Stencil.js vs lit-element vs Vanilla vs Shadow DOM vs Vue.js

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Aubrey Drescher

Aubrey Drescher

More from Medium

What Does Mean Stack Development Mean?

Ceiling Punch: Learning Flutter 2 weeks

Easy Start with Appery.io Cloud DB: Creating Ionic 5 ToDoList App

Flutter App Development: The Framework for Cross-Platform Applications