One of the benefits to using a JavaScript framework like Dojo is that they provide widgets that greatly simplify UI development. In this part of the lesson, we’ll talk about dijits, Dojo’s name for their widgets. The dijits we’ll focus on are the Layout dijits BorderContainer, ContentPane, and TabContainer.
So far in the course, the majority of our apps have had the map fill the entire browser window. Earlier in this lesson, we saw how to overlay UI elements on top of the map. However, there may be times when you want to draw the map in a smaller area of the page and surround it with other types of content. This can certainly be done with plain HTML and CSS, but JS frameworks like Dojo typically offer widgets to simplify the process.
The example below shows a layout with a sidebar and header built using Dojo’s Layout dijits BorderContainer and ContentPane. While the example has just placeholder text, you should be able to imagine content that you’d include in your own app. For example, the header could include the app’s title and maybe an organization logo. The sidebar could contain a listing of map features like we saw in the previous section. Note that the border between the map and sidebar is resizable, a nice feature for users that is made much easier to implement using a framework.
See the Pen Dojo Layout [1] by Jim Detwiler (@jimdetwiler [2]) on CodePen [3].
Let’s walk through the code that produced this page. While dijits can be added to a page dynamically using JS code, in this example they are defined using HTML. (In the Dojo documentation, adding dijits with JS is referred to as the programmatic approach, while using HTML is the declarative approach.)
The first difference in the HTML of this example as compared to earlier examples is the linkage to the stylesheet associated with Dojo’s claro theme. Dojo’s reference site [4] provides more information on the implementation of their themes, but the basic idea is that they produce a consistent look and feel to the Dojo elements placed on the page. The other step in implementing the theme is adding the theme’s class name to the body element.
The page’s body contains a div (with id of appLayout) that has its data-dojo-type attribute set to dijit/layout/BorderContainer, a dijit used to divide a page into as many as five regions. Here the appLayout div contains three child divs. The child divs are defined as ContentPane dijits and have their regions defined through the data-dojo-props attribute. The first (classed as centerPanel) is assigned to the center region and contains the viewDiv div you’ve seen used in earlier examples to hold the MapView or SceneView. The second div (classed as edgePanel) produces the narrow strip in the top region and the third div (also classed as edgePanel) produces the sidebar in the left region. Note also that the left region div includes a splitter: true property setting. This is what makes it possible to drag the border between the left and center divs to resize them.
A critical piece of implementing these dijits is the script element on lines 40-44. This code includes an AMD require() block just like we’ve seen for getting access to Esri’s API classes, except this one provides access to the Dojo dijit classes we just discussed above. Importantly,t the require block includes the dojo/parser module, defines a matching class named parser, then uses the parser class to execute the parse() method. This finds all of the elements decorated with a data-dojo-type attribute and converts them into the slick widget the user sees on the page.
One last important point to note is that the implementation of dijits as we're doing here changed at version 4.25 of the Maps SDK for JS. Prior to that version, Esri's content delivery network (CDN) hosted several Dojo modules as part of what you got when you loaded the Esri modules. Beginning at 4.25, the Dojo modules were no longer included. This means that loading those modules now has to be done separately, which is done by the script element on lines 10-34. This change in the CDN along with a discussion of how to incorporate the Dojo modules (packages) going forward is covered in the Release notes [5] section of the documentation.
The next dijit type we’ll discuss is the TabContainer, which can be used to present page content through a series of tabs. In the example below, I’ve built an app that displays three maps of the 2010 U.S. population by race, each under a different tab.
See the Pen Dojo Tabs [6] by Jim Detwiler (@jimdetwiler [2]) on CodePen [3].
The HTML of this app is similar to the previous example in the use of the claro theme and the BorderContainer and ContentPane dijits. In this case, I’ve embedded a div with a data-dojo-type of dijit/layout/TabContainer within the center region ContentPane. From there, the tabs are created by adding ContentPane divs as children of the TabContainer div. Each of the tab divs has its title attribute set to the label that should appear on the UI. Then inside each of those divs is an empty div that serves as a placeholder for three different MapViews. Note that the first of the three tab divs has a data-dojo-props setting of selected: true. This causes that tab to be the one that’s selected when the app first loads.
Moving to the JS code, a WebMap and MapView are created for each of the three divs embedded within the tabs (whiteDiv, blackDiv and hispDiv). The WebMaps display 2010 Census population data and were authored by an Esri staffer. They are associated with the appropriate div in the HTML through the setting of the MapView’s container property, as we saw earlier in the course.
Earlier in the lesson we saw that dates can be obtained from the user via the date input type built into HTML5. Another date picker option is Dojo's DateTextBox dijit [7]. This dijit is demonstrated in the CodePen below:
See the Pen Date Picker (Dojo DateTextBox) [8] by Jim Detwiler (@jimdetwiler [2]) on CodePen [3].
Looking at the HTML, you should note that the widget is actually created as an input element of type="text" (i.e., a "plain" text box). However, it has a dojotype attribute setting of dijit.form.DateTextBox, which is what causes it to be rendered as a calendar. Other attribute settings to note:
In the JS code, the setDates() function is immediately called upon when the page loads. That function creates two Date objects: one representing today and the other 30 days prior to today. Those JS Date objects are used to set the dijits' initial values and constraints (min and max possible dates). This is in contrast to the earlier date picker example, in which those attributes were set to strings in yyyy-mm-dd format.
The rest of the app works exactly the same as the earlier date picker example.
And paralleling the earlier page that covered the HTML5 date picker, below is an example built on the 2019 wildfire layer in which the DateTextBox dijit's values and constraints have been hard-coded within the HTML.
See the Pen Date Picker (Dojo DateTextBox dynamic) [9] by Jim Detwiler (@jimdetwiler [2]) on CodePen [3].
We've really just scratched the surface of Dojo widgets that could be useful in developing geospatial apps. I encourage you to browse through the Dijit documentation [10] to see some of the other UI elements that are available. Here are a few that are particularly useful:
You should also keep in mind that Dojo is just one of many JS frameworks that can be used to develop your apps. The Guide section of the SDK includes a page on how other frameworks [11] can be integrated into an Esri JS API app.
Links
[1] https://codepen.io/jimdetwiler/pen/qBLQNxw
[2] https://codepen.io/jimdetwiler
[3] https://codepen.io
[4] https://dojotoolkit.org/reference-guide/1.10/dijit/themes.html
[5] https://developers.arcgis.com/javascript/latest/4.25/#removal-of-non-esri-packages-from-cdn
[6] https://codepen.io/jimdetwiler/pen/JjweKyw
[7] https://dojotoolkit.org/reference-guide/1.10/dijit/form/DateTextBox.html#dijit-form-datetextbox
[8] https://codepen.io/jimdetwiler/pen/ZEMPywO
[9] https://codepen.io/jimdetwiler/pen/zYJbPGG
[10] https://dojotoolkit.org/reference-guide/1.10/dijit/index.html
[11] https://developers.arcgis.com/javascript/latest/guide/using-frameworks/index.html