Experience Builder Tips and Tricks

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Latest Activity

(77 Posts)
JeffreyThompson2
MVP Frequent Contributor

You are someone with some level of programming/web development experience (For this article, I will assume you are at a pretty basic level, but I think this will be useful for experienced devs as well.) and you are about to start on building a new project. You have a good outline for what you need to build. The main question now is how. You need to pick a framework. Are you going to build your application in Experience Builder Developer Edition or in the Maps SDK for JavaScript (AKA: the JavaScript API)? This post is here to help you decide. I'm going to talk about the major concepts, features and issues in both frameworks. If I think it's a point in favor I'll use green text (+), negatives are in red text (-) and we'll stick to black text if it doesn't easily fit into a binary.

Experience Builder

  • Drag and Drop Interface (+) - The Builder that all the Muggles who can't code use to make their applications is quite powerful. The entire history of web development can be seen as an effort to write as little CSS as possible and this interface can handle most of your CSS needs. You may find you don't need to write any JavaScript either.
  • Rapid Prototyping (+) - Using the Experience Builder Build Mode, it is possible to make a functional proof of concept application in a matter of minutes. If you can't build it, well now you know you have some coding to do.
  • Maps SDK for JavaScript (+) - Everything that the JavaScript API can do can be done through Custom Widgets in Experience Builder. This post is just a false choice fallacy.
  • React - React is the most popular modern framework in the world and for some good reasons. But if you haven't used it (or a similar framework) before the learning curve is steep. Do you really have the time to learn a new framework right now?
  • Redux (+) - One of the things that makes React hard to deal with is strict one-directional information flow. Redux allows you to send Messages from one part of the application to another giving you much more flexibility. Redux is so woven into Experience Builder that many developers may have no idea they are using it.
  • Storybook (+) - The Storybook has a ton of pre-built, pleasantly designed UI elements. They are generally easy to use and while the documentation is far from perfect it is generally sufficient.
  • Bootstrap (+) - You also get Bootstrap classes to help with your UI. Many options. Easy to use. Great documentation.
  • Documentation of the Functional Bits (-) - The documentation quality for developers in Experience Builder is terrible. TypeScript is almost always the best documentation source and...
  • TypeScript - Technically, Experience Builder is not written in JavaScript. It's in TypeScript. TypeScript is a superscript of JavaScript that "strictly enforces" typing. (It does not.) Done correctly, TypeScript makes the IntelliSense built into your IDE much better. But Experience Builder typings are frequently wrong, which costs this point it's green text. If IntelliSense gives an error code starting with TS, ignore it and see if it works anyway. It often does.JeffreyThompson2_0-1763409101504.png

     

  • Flexibility (+) - Want to make a single page map-centered application? You can do that. Want to make a hundred page application without a single map? Maybe consider a different framework, but you can do that.
  • Inflexibility (-) - Don't want to make an application using TypeScript in React and put it together in a Drag and Drop Interface? Then, get out of Experience Builder. Does this directly contrast with the last point? Yes.
  • Easy Set-up (+) - Click one button and start building in Node.js, React, Redux, Maps SDK for JavaScript...
  • Heavyweight (-) - Node.js, React, Redux, Maps SDK for JavaScript... Sounds like a lot of stuff because it is. Experience Builder is a bloated framework and its not easy on your network, hosting server or end-user's computer. You're driving an 18 wheeler, not a Ferrari.
  • Dynamic Content (-) - Let's say you had a list of 1000 Feature Layers and you needed to generate a page and map focused on each of them. Could you do it? Maybe. But not well. And you'll probably need a lot of custom code. 
  • Responsive Sizing - Experience Builder has three built in screen sizes to handle responsivity. Front-end devs know that really isn't enough, but there really isn't a mechanism for making more breakpoints.
  • Breaking Changes (-) - Are you expecting to update your application and keep it fresh through product updates? Experience Builder inherits all the breaking changes of React and the JavaScript API and more! And the Experience Builder Team likes to move stuff around and rename stuff, just for the fun of it. Be prepared to fix stuff every single update.
  • Overall Coding Experience (-) - Between needing to know React and the JavaScript API, the issues with responsiveness, constant breaking changes, and the lack of documentation, coding in Experience Builder is not much fun, especially for beginners. It does get somewhat easier and more fun after you've built a few dozen Widgets, but not much. @Jianxia, I cannot stress enough how much documentation counts in this category. 

Maps SDK for JavaScript

  • It Makes Maps - It makes maps and a few related things like tables and editing tools. That's it. If that's all you want, it does that. If you want to put something else on the page or make it look nice, you will need something else to do the job.
  • Flexibility (+) - It's up to you to pick what components you use with the JavaScript API. Want to use React or Vue or Angular? Sure, you can do that. Want to write raw HTML? You're a madman, but no one is stopping you. My first big project was in Django, which is a Python based framework. I had Python, JavaScript and HTML all happily (and grossly) co-existing on the same page.
  • Lightweight (+) - Because the JavaScript API only does one thing, it's much lighter weight than Experience Builder and it's pretty easy to pop into some other framework.
  • No Easy Set-up (-) - Well, you wanted to make a Django/React/Material-UI stack. So...you have to make it.
  • Components (+) - What if you could just write one line of code and have a fully functional Legend on your map? That would be pretty neat. That's what Components do. (Or Widgets, but you really shouldn't be using Widgets anymore. They are going away.) Hey, that sounds a lot like Experience Builder Widgets. Because they are and many Experience Builder Widgets are little more than loaders for JavaScript API Widgets/Components. If you are building a simple application, you may find Components can do all the work for you. Oh, and part of the reason Components are replacing Widgets is that Components are better designed to work in React-like frameworks.
  • Calcite (-) - Another part of switching to Components is to encase everything in Calcite. And unfortunately we are not talking about CaCO3. Calcite is ESRI's official UI design system. Working in the Maps SDK for JavaScript, you are expected but not required to use it. But it's going to get in your application whether you like it or not. I find Calcite confusing to use, it makes traditional CSS targeting impossible and the documentation is obtuse. Personally, every time I have tried to design something in Calcite, it has come out at least somewhat compromised. And, I don't think it looks all that good either. Calcite is getting into Experience Builder, too. But, you are at least one more step removed from it and you have the far superior Layout Widgets and Storybook to pull from to build your UI. If I could drench Calcite in 0.1 molar HCl and watch it slowly fizz away, I would.
  • Documentation of the Functional Bits (+) - The general quality of the JavaScript API is excellent. The properties and functions are clearly explained and there are many examples, even for some fairly complex builds. Although, they need to do some work to get the Component side of the documentation up to their overall standard.
  • Secret (+) - There is at least one thing you can do in the JavaScript API that can't be done in Experience Builder and it's Secret. I am not allowed to tell you what Secret is. Please do not ask about Secret. But Secret is a really good reason to pick the API over Experience Builder.
  • Dynamic Content - I can't give the JavaScript API green text on this because it can't really do dynamic builds on it's own, but with just about any modern framework, you can make it happen pretty easy.
  • Responsive Sizing - See above. There isn't anything in the API specifically to help you make dynamic screen sizes, but there isn't anything stopping you either.
  • Breaking Changes - Yeah, the JavaScript API team breaks stuff pretty often, Calcite and Components are causing a lot of issues, but at least they change stuff for a clear reason and communicate changes well. They're even changing the numbering system, so they can tell you when they're going to break stuff.
  • Overall Coding Experience (+) - Your milage may vary, but overall, using the JavaScript API is a fairly pleasant experience. There is a fairly low barrier to entry and the learning curve flattens out pretty fast.

Ultimately, I can't tell you which framework is better. The answer will depend on your goals and ability, but here is a workflow:

  1. Think about what you need your final project to do and look like.
  2. Have an honest conversation with yourself about your coding ability, capacity to learn, and time (or any other) constraints.
  3. Try an Experience Builder prototype, no code yet. If you hit a wall early, maybe switch to the JavaScript API. If the wall comes near the end, try sticking it out in Experience Builder.

more
4 0 175
JeffreyThompson2
MVP Frequent Contributor

Is this the strangest thing I've done? Maybe, I don't know. I've done some wacky stuff.

Challenge

  • Once upon a time, another developer here made a very good Public Notification Tool in using the ArcGIS Pro SDK.
    • Better than anything I could hope to make in Experience Builder, even with unlimited time.
  • ESRI is adjusting their licensing and pricing model in ways that will effectively give us fewer licenses at a higher cost per license.
    • So we are adapting by looking for ways to use less licenses, like moving some staff off ArcGIS Pro and onto web apps.
  • Personal Goal: Do not write any code for this project.
    • A year and a half ago, I wrote it's totally possible to make a Public Notification Tool in default Experience Builder, so I needed shut up and prove it.
    • I am competing with an existing, fully-functional, objectively better option, so I didn't want to put in too much effort only to be told they would rather just pay ESRI to stick with our current tool.

Solution

Used Near Me in Experience Builder to create a Public Notification Tool. I did it pretty much exactly the way I said to do it in that other post. It works. Good night.

...The Actual Challenge This Post Is About

"Ok, it's pretty good, but we need to be able to print a map with the buffered area and also a map with just the selected parcel highlighted with a yellow outline."

Near Me doesn't have an option to hide the Buffer/Sketch Area. It can only be cleared by clearing everything in the Widget. Nor is there an option to turn these things off completely. There are times such options would be useful. **Cough**

What If You Could Hide A Map Widget?

This isn't Fantastic Widgets and Where To Hide Them, the title I now deeply regret not giving to this post. No, you really can't hide a Map Widget. Good night.

...But you can disguise a Map Widget. Depending on how you build, the user may not have any idea you are using two maps unless that carefully examine the URL bar in their browser and can read Experience Builder. I've found at least three related versions of this build that could all be useful in certain circumstances. They really must be explained in order to make sense, but don't think that one version is inherently greater than another. Feel free to step off the elevator at floor one, if it suits you best. I did.

Grouund Flouour: The Extra U's Are Four The British Flouour Numbering

Do you really want to get on this ride? Are you sure? It gets weird. Ok, here we go.

I've already created a project with a Map, Near Me, Search, and Print Widget and configured them so they make a functional Public Notification Tool. I've renamed my Map Widget to Working Map and my Print Widget to Print Working Map. My Crude Demo App currently looks like this.

JeffreyThompson2_0-1762807618269.png

Floor 1: With A Button Switcher

Now, we slightly break stuff for a moment, as we send Working Map to the Pending List. And Add a Section Widget in its place. Rename this View Something You Don't Mind Being In A URL. Drag Working Map out of the Pending List and into the Section Widget.

Add a Button Widget inside the Map Widget and give it a Text of Hide Buffer Area. It's easiest to do this now, but if you're going to a higher floor, you may not want to do this.

Go back the Section Settings Panel and Duplicate Something You don't Mind Being In A URL. Then rename it to Something Else You Don't Mind Being In A URL.  Click the Map Widget and rename it Display Map. In the Options Submenu, set the Highlight Fill to transparent and the Highlight Outline to yellow. In the Action Tab, add an Extent Changes >  Working Map > Zoom To Action.

If you made a Button earlier, click the Button Widget and change the Text to Show Buffer Area and Set Link > View > Something You Don't Mind Being In A URL. Switch back to the original View and add an Extent Changes >  Display Map > Zoom To Action to your Working Map Widget and if you've got a Button, Set Link in the Button to the newer View.

Now, add another Print Widget and name it Print Display Map and set its Map Widget to Display Map.

So at this point I have one Map, that looks like the one above, that shows the buffered area and another Map that only has a yellow outline on the selected parcel. (I wish I had an option to make this yellow line thicker, though.) I can click on either map or use the Search Widget to trigger a Near Me analysis. The map areas stay in sync for display and printing purposes.

JeffreyThompson2_0-1762956487497.png

And I can print from either map, here I can show you...

JeffreyThompson2_1-1762956697392.png

...That's not supposed to happen. Here's where we get to the problems. In order to conserve resources, Experience Builder does not load a Datasource until it is actually needed. So, you cannot print a Map until you have viewed a Map, at least once. Once the Map has been loaded, you can print while looking at either Map and the data and map area should match.

Other issues:

  • The drawing tools in Near Me will not work while looking at the wrong Map.
  • Any other Widgets like Draw or Measure that require a Map to function will only work properly with the Map Widget they were configured to work with.
  • You may encounter some awkward zooming effects.

I am working on an internal application where the users can theoretically be trained to workaround and tolerate some less than ideal behavior. And this version has the best load times with an option to turn buffers on and off that works well in this scenario. If we go up a floor or two we can address some of these issues.

Floor 2: Only Show The Display Map

Let's say you are working on a build where you absolutely do not your user to know you are using Near Me and even the faintest Sketch is too much. Or maybe you are trying to handle that issue with the Print Widget without the user needing to do anything. Or you want to do some drawing on the Map without all the Near Me generated distractions. Then this is the floor you want to get off on.

This trick is as stupid as it is simple. Go to the Section Widget and turn on Autoplay. 1 Second Interval and make sure Loop is turned off.

JeffreyThompson2_2-1762962087007.png

To the user the Map will load, then it will flash and load again. And both Print Widgets will work without issue.

Note that this one second countdown doesn't appear to start until the data is fully loaded, which could be a pretty long time. These upper floors will also not load both Maps if the user includes the View URL Parameters to get to the site or just hits the reload button on their browser, which will reload with the URL Parameters included. 

If you made any Buttons to switch you Maps, you may want to delete them.

Floor 3: Only Show The Working Map

On this floor, the Working Map is the primary one with the Display Map being only used for printing. And it's super simple to get here from Floor 2. In the Section Setting Panel, drag the Something Else You Don't Mind Being In A URL View above the Something You Don't Mind Being In A URL View.

JeffreyThompson2_3-1762963582756.png

The Display Map will now load first then switch to the Working Map automatically. To me, this is the ultimate form of this technique and the one I would prefer to use, but it has a major downside. In testing, this version seems load much, much slower than the other options. As in, are you sure this isn't broken slow? And Near Me will be displaying a loading message further making this build look broken. I've got some pretty large datasets in my Map, so maybe this would work better if you have less data?

But maybe being slow isn't such a terrible thing. It appears that Near Me has a bit of a bug where if it is open when the project loads, it can load too fast, before the Map Widget loads and become permanently stuck on a Failed To Load error. This trick holds Near Me in a loading state until the second Map Widget loads and appears prevent such an error.

Can we take this even further?

Floor 4: There Is No Floor 4. You Bust Through The Roof And Now You Own A Chocolate Factory

iadedp4zkh471.gif

more
1 0 139
JeffreyThompson2
MVP Frequent Contributor

Do you work for a city or state government in the United States of America? Or some quasi-governmental entity like a school district? Did you know that the Department of Justice has ruled that your public facing websites must meet certain accessibility standards or you will be found in violation of the Americans with Disabilities Act and be vulnerable to lawsuits? The exact standards and timeline vary depending on the size of your organization, but for a city of over 50,000 people, it's WCAG 2.1 AA by April 24, 2026. That is alarmingly soon. (At least, if you are the person that needs to fix everything. If you need these features, it is painfully slow.) Are you ready? Have you started preparing?

For the record, the federal government is already required to meet these standards. So, federal workers should already be aware of the issue, but well... you guys have other problems right now.

You may have noticed that in the most recent updates ESRI has become increasingly focused on improving the accessibility of their products. Well, now you know why. Here's a big post with a bunch of links to ESRI's Accessibility Resources. And, of course, Experience Builder has been adding new accessibility helpers, but also of course, the Experience Builder team loves to hide the important new features.

It took me 20 minutes to find this magic button. Look in the bottom bar of the Builder. Do you see the letters A11Y? That's actually a Button.

JeffreyThompson2_0-1761332870514.png

Click it and you will see two sliders. Auto-Calculate Element Tab Orders In Fixed Layouts will tell screen readers what order your Page should be read in. It does have the potential to re-arrange your Layout, so be aware and be prepared to move things around again after turning it on. The other slider, Enable Accessibility Settings For Each Widget, will add a new sub-panel to the Settings Panel of every Widget.

JeffreyThompson2_1-1761333192427.png

The Accessibility Settings sub-panel adds two options to each Widget. The Accessible Label allows you to write a description for what a Widget does for the screen reader to read. Giving screen readers stuff to read is a large percent of meeting the compliance standards, so be sure to use this. The Enable In Skip To Checkbox makes the checked Widget a priority for the screen reader. This option is only available if the Widget is not wrapped in any other Widget.

JeffreyThompson2_2-1761333780695.png

Also in the redesigned Themes Color Tab, picking a Text and Background combination with insufficient contrast, should trigger a warning. So don't ignore those yellow triangles.

JeffreyThompson2_3-1761334063588.png

more
0 0 258
JeffreyThompson2
MVP Frequent Contributor

Experience Builder Tips And Tricks is officially turning two years old tomorrow and to celebrate ESRI has given me something to write about, something that has become increasingly difficult since I ran out of ideas a full year ago. Yes, expect these twos to be totally and truly terrible.

Birthdays remind us of traditions and Experience Builder has a tradition of putting a major bug into every odd numbered release that makes it essentially unusable (at least to me). This is Experience Builder 1.19, btw.  Let me check my math... 19 % 2 !== 0...yep, that's odd. Wonder what it will be this time? There's already a logged bug in the Feature Info Widget.

Frankly, I don't see anything I really need in this update anyway, but if you're on ArcGIS Online, you should be very excited because Themes have been totally redone to make them way better and even more visual customization options have been introduced for those of you who can't hack the CSS. Your apps are about to look a whole lot better. In six weeks, we'll find out if this breaks all the CSS hacks in Developer Edition.

Ok, let's properly get into it. Here's what happens in this series:

  • I read the official What's New in Experience Builder Blog post.
  • I maybe try a few things for a few minutes.
  • I attempt to translate the What's New page from developer to English.
  • If I don't think something is going to be very important to many people, I leave it out of my notes.
  • I might make some guesses how the new stuff can be used. (Tips and Tricks LLC offers no guarantees that anything said in this post will actually work.)

MapViewer Update That Will Help in Experience Builder

Settings to make overlapping labels look better.

Accessibility

You can now enable a subpanel in the Settings Panel of every Widget that allows you to set screen reader text and make a Widget a priority for screen readers. The option is not on by default and it's super hard to find to make you feel what it's like to use a website that does not have good accessibility practices. Great on ESRI for promoting empathy for those with impairments. This will probably be in separate follow-up post, but look for A11Y in the bottom bar of the Builder to get these options.

The Widget Controller is now accessible and the List and Search Widgets can tell you about Suggestions and Search Result Changes. 

The Chronology, Frame, Preface and Ribbon Templates have been accessibility optimized.

Builder

ESRI has fixed a major UI issue that has led to many new Builders coming to this site and asking why they can't add Widgets to their projects. If you have the Lock Layout or Live View options enabled, the Add Widgets Button Panel is inaccessible and if you try to click on the button, it will give you an option to turn those settings off.

General Settings

You can restrict Pages by User Types or Group Membership. Now, no one (but Admins that ignore any such restrictions) will know my dark, painful secrets.

Style Settings

Set the Foreground Color in the Background Settings. I don't know if it would be possible for ESRI to have written this section in a more confusing manor, but here's the deal: If you change the Background Color of a Widget it may not work well with certain Buttons/Text, now you can change that color, too.

Templates

New Template called Compass. It's Grid style. You can also find Templates from ArcGIS Online and Living Atlas.

Themes

The true star of this update. Themes have been thoroughly revamped. You can now define more than just a Primary Color. And if you make a bad choice and make your text unreadable, it should give you a warning. I'm just going to show you this Panel so you can see for yourself how many color choices you have now.

JeffreyThompson2_0-1761233534011.png

In the Typography Tab, import any font from the massive Google Fonts library. And the text dropdown menus are now written in their fonts. (Did one of my snarky, off-hand comments do this?)

The More Tab has some additional hard to categorize stuff like how round are your borders, what color are the text inputs and should your Links be underlined. Modern web design has drifted away from making Links stand out and Experience Builder defaults have followed suit, but accessibility standards do still prefer blue underlined Links.

Warning: If you convert app to one of the new Themes, there is no going back. So, it's probably best to Save A Copy of your project, before clicking one of the new Themes. It's going to change a lot of stuff.

Windows

Windows can be resized by dragging.

New Widgets

Image Collection Explorer - View individual images from a Dynamic Imagery Layer. You can even make new Imagery Layers.

Login - Sign people in or out of your app. Send them somewhere when they sign out.

Widget Updates

Accordion/Column - There's a Button now for adding Widgets to these Widgets. I was planning to say all Layout Widgets can do this, but no. Fixed Panel, Sidebar, and Row still have no equivalent option.

Add Data - File Geodatabases are now supported, but must be compressed to a ZIP file first. Exports are now allowed as well and you can choose what export types are allowed. Allow your users to upload their file or grab a web resource, do some editing or filtering, and then download the processed results.

Analysis - Can turn the results into a Map Service.

Basemap Gallery - Popups can be turned off for basemaps added by URL. It respects your organizations basemap ordering.

Business Analyst - Better UI tells users what Infographics are available to them. Exporting an Infographic comes with a  Credit Usage Estimate.

PSA: Creating, viewing and exporting Infographics in Business Analyst inside or outside of Experience Builder costs Credits. Probably way more than you realize.

Chart - I haven't really done charts in Experience Builder, so I feel a little lost, but I think this should make sense if you're doing charts, so I'm just going to copy this paragraph in.

When setting intervals for time bins, you can now choose to have intervals be rolling windows, where the intervals are aligned to the first or last data point, or use calendar-based units of time. Additionally, you can use the new Prefer to use label check box to choose a sorting method for sort-by fields. In By field mode, check the box to sort by field label (alias) and uncheck the box to sort by field name. In By category mode, check the box to sort by attribute label (description) and uncheck the box to sort by attribute code (coded domain).

Edit - Batch Editing is now allow in Attribute Only Mode. Editing will stop if you put the Edit Widget in a Widget Controller and close it. Split and Merge are now available. And with that, Experience Builder has reached full functional parity with WebAppBuilder and everyone was super chill about this sentence in the comments. 

aa04nq.gifFilter - Filter with URL Parameters. Some choices that didn't allow the Expanded List Input now do and some choices that didn't allow the Pill Selector Input now do. See the official post for details.

Correction: The Expanded List is actually a brand new style of Filter. It looks like this:

JeffreyThompson2_0-1761308667927.png

 

Breaking Change Alert: GlobalID and GUID fields no longer allow partial matches.

Grid - Getting stuff to go where you want in the Grid Widget can be a bit frustrating at times. Insert Before and Insert After Buttons should make it a little easier.

Image Display Order - The Display Order Widget has a new, slightly longer name that better describes what it does.

Map - There have been a lot of requests to be able to restrict map extents. That's sort of possible now, as you can now limit the allowed Zoom Levels. Combine this with removing the map panning options and give the user Bookmarks or some other way to move to points of interest and you can trap them somewhere... Forevvvvvvvver.....Hahahahahahaha...Happy Halloween.

Pick a style for your Scale Bar. Tigger Near Me with the Locate Map Tool. And, use URL Parameters to set the Zoom Level.

Map Layers - Mosaic Sub-layers can now be customized. Remove layers added during runtime. If your search results are in a Group Layer, the Group will expand automatically.

Most importantly, what's not in this update, the Layer Batch Options still do not respect Layer Customizations. @Jianxia, we really need a way to make thematic layer groupings. This is one way. Bookmarks that don't change extents would be another. Can we get one, or preferably both, please? And...

My Location - Zooming to a new location is now optional.

Menu/Views Navigation - The color of the arrows is now an option.

Near Me - Calculate the length or area of intersecting features and include this in exports.

Oriented Imagery Viewer - Force zooming to the extent of Oriented Imagery Layers.

Search - Breaking Change Alert: URL Parameters have been renamed. serviceEnabledList is now enabledList and searchText is now text. Bet this is going to annoy a lot of people.

Table - Configure every tables for every layer at once, but you can still change stuff for just one table if you want. Restrict the tables to the layers in the map extent if you want. Choose between scrolling or a multi-page table. Keep a row at the top or bottom of the table always visible.

Timeline - Do 3D stuff now.

Widget Controller - Customize the size of your Widget Controller Buttons. Wonder where they got that Idea? The icon size and spacing is also customizable. Resize the Widget Panels with your arrow keys. Put a Widget Controller in a Widget Controller. Maybe you could make a neat nested menu, but remember that if you try to put a Button Widget in a Widget Controller it won't just work, it will pop-out a Panel with a Button in it. Would be nice if Buttons in a Widget Controller just worked. 

That's the end for this update and we are beyond WebAppBuilder now. It's Season Six of Game of Thrones and the show has reached the end of the books. I'm told that's when it really gets good. 

JeffreyThompson2_0-1761249384451.jpeg

more
12 0 522
JeffreyThompson2
MVP Frequent Contributor

Way back when, I indirectly, sort of promised a How To Install Developer Edition post and then never actually wrote it. And like everyone, I've been thinking a lot about AI for the past few years. Questions like "How can I do my job better with AI?" and more worryingly "Can AI do my job without me?" So what if we mix these ideas together and see if it turns into something worth reading? Remember when ChatGPT was new and every YouTuber did a "I asked ChatGPT to write this video" video, that's what this post is. First Microsoft Copilot is going to tell you how to install Developer Edition, then I will explain why I don't* use generative AI to help me with Experience Builder. 

The following was generated by Microsoft Copilot. It has gone through a few AI revisions (and some small manual style edits) including "re-write based on the style of the ESRI Community Experience Builder Tips and Tricks Blog". Red text used to indicate something to type into a console terminal.

Introduction:

Hey Team! Ready to dive into the world of custom web apps, widgets, and themes? This blog will guide you through installing the Esri Experience Builder Developer Edition. Let's get started!

Steps to Install:

Create a Client ID:

  • Log In: Head over to your ArcGIS Online or ArcGIS Enterprise account.
  • New Item: Go to the Content page and click "New Item."
  • Application: Choose "Application" and then "Other application."
  • Fill Details: Enter the required fields (like Title and Folder) and save.
  • Credentials: In the Credentials section, add https://localhost:3001/ in the Redirect URLs.
  • Save: Save and copy the Client ID for later.

Install Server Service:

  • Node.js Check: Ensure you have the recommended version of Node.js installed. Run node -v in your terminal to check.
  • Download & Unzip: Grab the developer edition of Experience Builder and unzip it.
  • Terminal: Open a terminal and navigate to the unzipped folder.
  • Install Dependencies: Run npm install to get all the necessary files.
  • Start Server: Kick off the server with npm start.

Troubleshooting Tip: If npm install fails, check your internet connection or ensure you have the correct Node.js version.

Install Client Service:

  • New Terminal: Open a new terminal window and navigate to the client folder inside the unzipped Experience Builder directory.
  • Install Client: Run npm install to set up the client service.
  • Start Client: Start the client service with npm start.

Conclusion:

By following these steps, you'll have the Esri Experience Builder Developer Edition up and running on your computer. This will enable you to create and customize web apps with ease. If you run into any issues, check out the official Esri documentation or reach out to IT support.

JeffreyThompson2_0-1755631268770.jpeg

Did the machine get it right?

Yeah, if you follow these instructions, there is a chance you will get a working copy of Experience Builder and it's way more readable than the official installation guide. However, it does leave out the why of it all, makes an odd but valid choice, and omits key bits of troubleshooting that will trip up a lot of users. If there was some human developer with practical experience writing this guide they would probably add something like this...

  • The Missing Why
    • Creating a Client ID links Developer Edition to your ArcGIS Online/Enterprise account functioning as a sort of password when you log into the Builder.
    • The installation files downloaded from the ESRI website are not all of Experience Builder. A full installation of Experience Builder involves downloading thousands of additional files through Node Package Manager, npm.
  • The Odd But Valid Choice
    • The robot recommends running npm install while ESRI says to use npm ci, which stands for clean install. Either of these commands should work, but ci is the better choice. The clean install command will first delete any Node files you already have in the folder before downloading the Node packages. ci is CYA in case of something like a previous incomplete installation.
  • The Key Bits of Troubleshooting
    • Running npm install or npm ci (or npm i) should take a few minutes filling your terminal up with lots of words, warnings and loading bars. It should look kind of scary.
      • It is kind of scary. You are downloading thousands of files from hundreds of different sources. Better hope some North Korean spyware isn't in there.
    • If it completes very quickly with some error including the letters SSL or never completes and just makes a spinning line, the downloads are probably being blocked by SSL security. I put the odds of this happening at approximately 99% the first time you try to install a Node package.
      • Running npm config set strict-ssl false before npm install will disable SSL security and allow the downloads to complete.
      • This is not entirely safe. See North Korean spyware above.
      • After running npm install, it would be a good idea to use npm config set strict-ssl true to turn SSL security back on.
    • I had issues unzipping the 1.18 version of Experience Builder. By default, Windows does not allow file paths to be longer than 260 characters and this latest build of Experience Builder is getting awfully near that limit. I had to unzip the files to the root of my C drive to get around this restriction. 

Ok, so the robot can do an adequate job of installing Experience Builder...

Why don't* I use it? 

There are a lot of reasons to not like generative AI, like a lot a lot. But, this isn't a high-minded critique of the concept of generative AI. I don't use AI to help me with Experience Builder because I don't think it will work very well. When working with AI, it's important to remember how it actually works. AI doesn't know anything, it's just guessing what the next word (or pixel for image generators) should be. This creates a number of challenges for an AI model:

  1. Not enough documentation: In order to build a good AI model for Experience Builder, there would ideally be thousands of working, publicly accessible examples of working code blocks. For many frameworks and languages, there are plenty of good examples, but as I have stated many times there is not enough documentation for Experience Builder. It's the reason this blog exists. Even worse, the greatest source for minable data on Experience Builder is here, ESRI Community, which contains mostly non-working code.
  2. Experience Builder is new and changing fast: Experience Builder is about five years old which even in software terms isn't that old. And, it changes considerably three times a year. If you mine this site for data, you would learn that Experience Builder can't handle related records, put text on a map, filter more than one thing at once, or use Arcade. None of those things are true anymore. Good luck to the machine (and everybody else) figuring out what is and isn't true anymore. (Hey look, one of those really good reasons not to like generative AI.) I can't find a data cutoff date for ChatGPT-5, but I doubt it was trained on the June 2025 update.
  3. Experience Builder is complicated: Experience Builder is a framework built on top of an API built on top of another framework with a bunch of other libraries added in built on top of a language. Did you know when you are working in the Build Mode, there are actually two separate simultaneous React trees running on the same page? How is that even possible? Good luck to the machine (and everybody else) figuring this mess out.
  4. Experience Builder is highly visual: Many of the questions on this site come down to, "Help me navigate the Experience Builder UI." There is almost no chance that AI will be able to answer any question like that effectively. On a somewhat related note: check out this blog post of hilarious AI attempts to draw a map. Unfortunately, I was rejected from the prestigious Texas Institute of Technology and Science many times. 
  5. You are a pioneer: If you are a person asking a question in the Custom Widgets Group or posting a new Widget there, there is a good chance that no one has ever done what you have/are trying to do. Or at least, they haven't written about it before. AI really can't make something for the first time. You have to take the test first, so AI can cheat off your paper. Look back at our positive example from earlier. The robot read the official ESRI documentation and re-wrote it in a more readable form. That's something AI is genuinely good at. But it missed at least one very important stumbling block, because it's not really documented. If you were counting on the Copilot to land the plane on it's own, you probably would have crashed.
  6. Mixing Class and Function Based React: Experience Builder was initially developed at a time Class-based React was still the standard. Many of the older Widgets and coding examples are still written in Class-based React. But Function-based React became the standard basically the day Experience Builder was initially released. So now the code base and samples are a mixture of the two React systems, which is practically two different coding languages. Good luck to the machine (and everybody else) figuring this mess out.
  7. Taylor Swift: I don't know how that woman seems to find her way into every important cultural discussion, but here we are.its-me-im-the-problem.gifIf you are counting on an AI model to accurately tell you how to fix something in Experience Builder, it probably isn't great that a significant portion of the documentation is this blog. Trailing off for mid-sentence jokes is not ideal data for glorified auto-correct to learn from. Am I writing this way to intentionally poison AI models? No. Am I upset if I am poisoning AI models? Also, no. If someone has a ChatGPT log about Experience Builder that suddenly veers off and starts talking about Bigfoot, please, please post it in the comments.

*I'm a lying liar.

Yeah, I totally use AI all the time to help me with Experience Builder. It's a running joke in the programming world that coders are just professional Googlers and it's pretty true. I don't know how to do anything, but I know how to look stuff up and figure it out. Not so long ago if I needed to figure out how to do something, I would dig through W3Schools, Mozilla Developer Network, GeeksForGeeks, or StackOverflow looking for some help. Now, every Google search comes with a free AI generated answer and more often than not, the Google bot tells me what I need to know. The Google bot saves me the time of reading through all these other sites and figuring out if what they are saying is actually relevant to my problem and it presents its answer in a clearer form.

Often these searches are for simple common programming tasks, like filter an array by another array, that I could probably figure out on my own but just don't want to. Or I know a function exists, but I don't know its name or syntax. For example, both JavaScript and Python have a built-in function that will find if a sub-string is in a string. In JavaScript it's called includes() and Python it's contains(). And I will never get that right on the first try.

Checking my work in the last paragraph...

Here's what the Google bot says about Python contains():

In Python, the most common and "Pythonic" way to check if a string contains a substring is by using the in operator.
Using the in operator:
The in operator returns a boolean value (True or False) indicating whether the substring is present within the main string. [1]
main_string = "Python is a versatile language."
substring = "versatile"

if substring in main_string:
print("Substring found!")
else:
print("Substring not found.")
Other methods for checking substring presence:
 
While the in operator is generally preferred for its readability and simplicity, other methods exist:
  • __contains__() method: This is the underlying method that the in operator uses. You can call it directly, though it's less common.
    main_string = "Python is a versatile language."
substring = "versatile"

if main_string.__contains__(substring):
print("Substring found using __contains__!")
  • find() method: This method returns the starting index of the first occurrence of the substring if found, and -1 if the substring is not found. You can use this to check for presence by comparing the result to -1. [2]
    main_string = "Python is a versatile language."
substring = "versatile"

if main_string.find(substring) != -1:
print("Substring found using find()!")
Case-Insensitive Checks:
 
To perform a case-insensitive check, you can convert both the main string and the substring to the same case (e.g., lowercase) before using the in operator or other methods.
main_string = "Python is a versatile language."
substring = "VERSATILE"

if substring.lower() in main_string.lower():
print("Substring found (case-insensitive)!")
AI responses may include mistakes.
 
See, what I mean? I was wrong in ways I wasn't even expecting.
 

 All of this is to say if you say, "Yo, Yo, Yo, ChatGPT. Write this Widget for me", what you get will almost certainly not work and you'll spend more time trying to fix it than if you started from scratch. But if you say, "I need instruction. Help me with this function", you might get something useful. Especially if you can de-contextualize the problem, outside Experience Builder, to be about React, JavaScript or even the ESRI JavaScript API. Make sure to read @JeffFranzen1's comment below for some great practical AI tips.

I'll leave you with this quote from Agent Smith.

1990s-were-the-peak-of-our-civilization-everything-after-is-v0-b6556o0n4qkc1.jpg

If you stop thinking, the robots win.

more
5 1 699
JeffreyThompson2
MVP Frequent Contributor

Here at Tips & Tricks Enterprises LLC. we love hiding Widgets. But, we've never done a dedicated post on the topic. So let's make a list of all the fun ways we've found to use invisible Widgets and all the different ways they can be hidden. Long time readers may be shocked that there is more than one way to hide a Widget because I have a strong preference for the Sidebar method, but it's not the only option nor the only one I actually use.

And before any Online/Enterprise users click away, there are ways and reasons to hide Widgets in every version of Experience Builder.

First of all, a list of all the hacks we have found that involve an invisible Widget. If you know anymore, shout them out in the comments and let's keep this list updated:

So, we have covered the why of hiding Widgets. Here comes the how.

Make It Tiny (Any Version)

In the Style Tab of the Settings Panel, set the Width and Height to 0px.

...You're still here? It's over. Go home! Go!

 Actually, there is a little more to this hiding technique because it doesn't quite work. Experience Builder won't really listen to you if you set the size to 0px. The smallest size it actually allows is 16 by 16px. Which means you have a 16 by 16px version of The Sidebar Problem™, so you will need to shove it in some 16 by 16px area of non-interactable space. There's also some potential issue here with screen readers and other accessibility aids. 

Send To Back (Any Version)

The Style Tab of the Settings Panel also has a Send To Back option. Can you use that? Maybe? It seems like in a lot of arrangements this button doesn't actually send it to the back. I also suspect this would be really bad for screen readers. Can't recommend this option.

Negative Pixels (Any Version)

One last option in that Style Tab is to click on that crosshair thing, set it to px and put in an absolute value big negative number, like -1000px, and watch as your Widget flies off the screen.

JeffreyThompson2_0-1754666398986.png

This is probably the best choice on the Style Tab, but maybe your Widget will re-appear on one of those huge curved monitors that are becoming increasingly popular. And again, I suspect this won't work great with a screen reader.

CSS (Developer and Enterprise Edition)

Give your Widget an id, let's call it "superAwesomeWidget". Now we can target it with CSS and make it vanish.

#superAwesomeWidget {
   display: none;
}

Hiding Widgets this way circumvents the 16px restriction in the Style Tab and it should also hide it from screen readers. Widgets can hide themselves, so that CSS Widget you uploaded to your Enterprise can include CSS targeting itself. Or you can target the Widget from another Widget, if you want to hide something ESRI made. Although it may be difficult to find the right class or id to target an ESRI Widget, especially without hitting other Widgets as well. All in all, if you are making a Custom Widget that you don't want anyone to see, I recommend this choice.

Column or Flow Row Widget (Developer and Enterprise Version)

Has the TV remote ever slipped between the couch cushions and practically disappeared from existence? That's what we are doing here.cat-climbs-out-of-couch-im-ready.gif

This is only going to work on Custom Widgets with no inherent height, but if you have a Column or Flow Row Widget in your application set the Gap on the Column/Flow Row to 0px and slip your Widget in there. Then, set the Height (for a Column Widget) or Width (for a Flow Row Widget) to Auto. I don't think this trick will be a problem for screen readers either.

Sidebar Widget (Any Version)

Alright, we've done this one before...

Get a Sidebar Widget and put your hidden Widget in the Collapsible Side. Set the Size to 0px, turn off Resizable, set Default State to Collapsed and turn off the Collapse Button. Your Widget is now hidden in an unopenable Sidebar. If screen readers try to read this, we have a big problem.

JeffreyThompson2_0-1754675705184.png

There you go. The comprehensive guide to why and how to make Widgets vanish.

They say the greatest trick the Devil ever pulled was protecting Kevin Spacy from any legal consequences.They say the greatest trick the Devil ever pulled was protecting Kevin Spacy from any legal consequences.

more
2 1 570
ShareUser
Esri Community Manager

Thank you to everyone who attended our session ArcGIS Experience Builder: Tips and Tricks at the Esri User Conference in San Diego last week! If you missed the session or want a refresher, read this recap.

Read more...

more
3 7 798
JeffreyThompson2
MVP Frequent Contributor

It will be is was* ArcGIS Online Update Day again, so it's time for the fourth addition of our First Thoughts series. Before we talk about what the official development team has been up to, I'd like to shout out the work of the unofficial development team: us. We have been super busy coming out with a lot of new high impact Widgets over the past couple months. I have been struggling to keep up with the changes in the List of Custom Widgets. Some of the things added by these Widgets include: freehand drawings and editing drawing symbology, changing map symbology at runtime and saving the state of an application. Features that don't now have OOTB support in Experience Builder. But make sure to keep checking that list often, there's still many ways the Community is ahead of ESRI. Other headline grabbing features in the June '25 Update include: advanced formatting options, Arcade support, and batch editing. All in all, this is the most impactful update in at least a year.

Here are the rules for this series:

  • I read the official What's New in Experience Builder Blog post.
  • I maybe try a few things for a few minutes. (That's a big maybe today. ESRI is having a bad day.)
  • I attempt to translate the What's New page from developer to English.
  • If I don't think something is going to be very important to many people, I leave it out of my notes.
  • I might make some guesses how the new stuff can be used.
  • You don't get mad at me if you can't actually do those things.

Accessibility

Accessibility features have been added to a ton of Widgets and Template. If you are working for a government entity, you probably have legal accessibility targets to hit, so make sure you are using whatever tools are available. If you aren't working for a government entity, try to hit those accessibility targets anyway. 

Actions

  • Open View will open a View in a Section Widget. (Is this new? Didn't we already have this?) 
  • Toggle Widget lets you open and close a Widget in a Widget Controller. This DIY Widget Controller build just got better.
  • Add Marker lets you point a point on a map.
  • With the Add/View in Table Actions, you can decide to open in a new sheet or not.
  • Export Data as shapefiles, geodatabases or KML.

Advanced Formatting

This might invalidate like half the posts on this Blog. Use your data to change text, image sources, links, backgrounds, borders and more. Do it no-code or write some Arcade for more complicated stuff.

Data

  • Datasource IDs are no longer a mystery. (Unhiding the Widget IDs would also be nice.)
  • Search for data outside your organization, if your Admin says it's ok.
  • Add data with Arcade.
  • New field types:
    • Big Integer - Don't you hate it when you can't count past 4,294,967,296? Now, you can count to 9,007,199,254,740,991.
    • Date Only - For timeless days.
    • Time Only - For dayless times.

Embedding

There is a new policy involving the Embed Widget, which I believe is more strict than it used to be and (if it is more strict) will break some of your apps. Here's the quote, then we'll talk about what it means and why they are doing this.

There are new rules for sharing authentication. ArcGIS uses token-based authentication for all access requests. When you embed an Experience Builder app in another ArcGIS app with the arcgis-auth-origin URL parameter, the Experience Builder app requests an access token from the parent app. The parent app decides whether to reply to the token. When you embed another app in an Experience Builder app with the Embed widget, the parent Experience Builder app only replies to the token request if the child app is under the*.arcgis.com domain or the same domain as the parent Experience Builder app.

The Embed Widget works using something called an iframe, that allow a little bit of one website to show on another website. In ye olden days of the Internet, iframes were very common. They are less common now for two reasons: branding and security. Many large websites have code that will reject connections from iframes. If you try to embed google.com, you will see a google.com refused to connect warning because Google doesn't want you to pretend you are Google. But the security problems are really the main reason for the downfall of iframes. Depending on the security settings of the iframe, the browser may have no way to tell where your website ends and the other website begins. So if you aren't careful, if the website you are embedding has a security issue, your website has a security issue, too. 

In order to access secured features, the embedded and parent site need to do a super secret handshake. Experience Builder won't take part in this handshake unless its with arcgis.com. If you are on Developer Edition, both apps can be on yourcompany.com.

General Settings

Remember this from WebAppBuilder?

JeffreyThompson2_0-1750967771520.png

 

 

 

It's in Experience Builder now. Restore your app state. Restore your heart.

Because of the major ArcGIS Online outage today, I have been dealing with complaints all day about login prompts and inaccessible content warnings. It's getting near the end of the day and I'm only this far through the What's New page. A few weeks from now, when the new Developer Edition comes out, I will be able to turn these login prompts off forever and then I can die happy. 

Languages

Do you need to translate to Norwegian? NO. That's what it's called now.

Pending List

The Pending List has been redesigned to clarify what, if any, screen sizes a Widget is used in.

Templates

Set sail on the new Templates called Harbor and Beacon. The Capabilities Button will help you decide which Template you should use.

New Widgets

I don't think I will ever use any of these new Widgets, but they sound useful to the people that will need them.

Display Order - For controlling mosaic datasets.

Document Explorer - Find ACC or BIM 360 files and folders then view them with 👇.

Document Viewer - See those ACC or BIM 360 documents.

Link Explorer - Find ACC or BIM 360 files linked to your map then view them with 👆.

Widget Updates

Add Data - Look, I said I would ignore pointless stuff, but this is just so pointless that it deserves recognition: there's a button to copy the sample URLs. Actually useful updates: symbology of imported layer will be respected and an option to limit the types of data imported.

Analysis - Support for geoprocessing of security enabled layers.

Business Analyst - New ESRI Tabular Reports template. If your American, your data can automatically update once a year. Rest of the world... look, it's been kind of rough around here lately... can you just let us have something?

Chart - Label your pie. Personally, I will label every slice 'mine'.

Directions - End users can save their routes. Builders can add a lot of barriers and define start and end points.

Draw - Freehand drawings and editing the symbology after drawing means ESRI has caught up to @RobertScheitlin__GISP three and a half years ago. Edit multiple graphics at once. @Brian_McLeer, they beat us on that one, but we still maintain the overall lead.

Edit - It was promised in each of the last two updates, but this time it actually happened: batch editing. Enjoy.  Change the attributes, size, location and rotation of multiple features at once. Cherish it.

Other stuff: Line segment length labels for 3D scenes. Reorder the layers. If you add data using Arcade, the editor can edit it. Faster layer loading.

Elevation Profile - You can choose whether or not to clear the results when the Widget closes or hides.

Feature Report - Make a report from any feature layer. Survey123 is no longer required.

Filter - Change the order of predefined values. 

Floor Filter - Your floor aware stuff just got way more floor aware. I don't really do Indoor stuff, but from the description, it sounds like floor filters actually work the way you would expect them to now. Also, floor aware Arcade editing support.

Flow Row - Add the Space Around and Space Between attributes to complete the Flexbox CSS options. Space Around is my favorite flavor of Flexbox.

Image - Expand your images. Pan around. Zoom and Enhance. Click arrows or swipe through multiple images. Make Tinder for geographic features?

Legend - Hide layers from your legend, including runtime layers.

List - Comma separator for the count of long lists. (Europe is really getting shafted on this update.) Checkmark if you're using a sort.

Map - Add a marker or lots of markers to the Map using URL Parameters. By default, 3D scenes render in lower quality on iPhone, so overpriced, underperforming phones don't explode.

Map Layers - Change the symbology of layers added at runtime. This is making fancy Widgets to add/remove data at runtime look even cooler. According to a promise made by @Jianxia at DevSummit, the show/hide all layers button should respect the Map Layers customization. According to testing, it does not. I will bring this up on every update until it does.

Measurement - A few updates ago, the Measurement Widget had snapping turned on by default. Since then many users have reported serious performance issues with it. And maybe, you just don't want snapping. Now, snapping can be turned off by the Builder. Or you could use a Draw/Measurement Widget where snapping must be deliberately enabled by the user.

Near Me - A whole lot of map surround options have been added to PDF reports. You can choose whether or not to clear the results when the Widget closes or hides. Hope this doesn't break all the fun hacks that depend on a hidden Near Me Widget.

Oriented Imagery Viewer - Make your own version of Google StreetView with Directional Navigation. Or define some other order for Sequential Navigation. Support for video. Use triangulation to the distance, area and location of stuff. These are things that make you say we really are living in the future.

Print - Pick what WKID to use for printing.

Query - Not in the What's New document, but my email says the broken Query Widget from the last update is unbroken and some quick testing confirms it.

Search - Search results that match what's been searched appear first. (Why wasn't it always like this? What was it doing before?)

Select - Reorder the layers in the Select Widget. It took a weird, unintuitive click sequence, but it can be done. Also, not in the What's New page, but if you place a Select Widget in a Widget Controller and close it with a select tool enabled, it will disable the select tool.

Share - Write the text that will appear in the email when a user shares by email.

Table - Support for showing and editing related records. Hovering over something in a Table will highlight the feature on the map in yellow. Option to automatically add runtime generated layers as tables. Decide what order you would like the tables to be in. Text display options, most importantly, text wrapping. Option to hide the Show/Hide Columns option.

That's all the notes for this update. The expect the next update to include those last set of edit tools missing from WebAppBuilder, just a bit too late for Enterprise 12.

* I got an early jump on writing this post this time around, but with all the disruptions caused by the ArcGIS Online outage (ESRI broke Nearmap real bad.) and the amount of stuff in this update. I couldn't get this all written up on update day. Sorry, I tried.

more
10 2 809
JeffreyThompson2
MVP Frequent Contributor

Three Buttons for the Pages under the URL,

Seven for the Views in their Section homes,

Nine for Widgets doomed to close,

One for the link on an external site

In a Sidebar where a hidden Widget Controller lies.

One set of Buttons to rule them all,

One set of Buttons to find them,

One set of Buttons to bring them all,

And in a Header bind them,

In a Sidebar where a hidden Widget Controller lies.

- J. R. R. Tolkien, probably, the books are really long and often quite boring.

Picture a project with a Widget Controller in the Header. From this one set of Buttons, you could jump from Page to Page in a project, change Section Views, open and close Widgets and Sidebars and link to external webpages.

... But they were all of them deceived, for there wasn't a Widget Controller in the Header, it's a set of Buttons.

A while back, I made a DIY Widget Controller. It was complicated to set up and probably not worth the effort. Today, I thought of a better way to pull off this trick and some more ways it could be used. The trick is just use a Widget Controller after-all. You may still want to use the self-changing Buttons from that post to add even more refinement. Note: we are building in ArcGIS Online. Older versions of Enterprise will not have all of these options. I'm too lazy today to figure out how far back this build is viable for.

Widget Controllers are cool and all, but they aren't without issues and almost all of them can be fixed by hiding your Widget Controller and replacing it with Buttons. Here are some of the problems we can fix this way:

  • Buttons placed in a Widget Controller don't just do what the Button should do, instead they pop-out a Button in the Widget Panel. So, they don't really work well for making links or controlling Section Views.
  • Widget Controller Buttons are icon only. The title of the Widgets can be added below the button with the Label option, but these titles are frequently cut-off.
  • Limited style options.
    • Only three sizes of buttons, unusably tiny, tiny and acceptable but still a little small.
    • Only two shapes of buttons, circle or square with rounded corners.
    • No borders around buttons.
  • All the buttons must have the same style, so no thematic coloring buttons.
  • All the buttons must be next to each other in a vertical or horizontal line.
  • All Widgets must float next to the Widget Controller or open at the same Fixed location.

Do you want to give this a try? Alright, let's make some Buttons that control a Widget Controller. For this build, I will be making basically just a standard Widget Controller, but with larger buttons that have a border around them. They will be neatly lined up, single-color, circular, icon-only buttons. But if you want to mix in some normal Buttons amongst your Widget Controller Buttons, or have radically different styles and for each Button, that's your choice.

Starting from a blank layout, I will add a Sidebar Widget and make it Full Size. Into the Collapsible side of the Sidebar, I'll add a Widget Controller and throw a few Widgets inside it. You must used the Fixed Widget Panel Arrangement for this build, but if you want your Widgets to open in different locations, you could use multiple Widget Controllers. The Always Open side will contain the actual application. I'll put a Full Size Map Widget here to fill the space. The Widget Controller is now set up, so we don't need to look at it again. In the Sidebar Settings Panel, set Resizable to off, the Default State to Collapsed, click that Collapse Button to close the Sidebar, and then turn off the Collapse Button so the user can't open it.

JeffreyThompson2_0-1749585183839.png

Now, we build the counterfeit Widget Controller.  Add a Flow Row Widget and in its Style Tab set the Width and Height to Auto. Add a Button Widget to it.

JeffreyThompson2_1-1749585502547.png

In the Button Settings Panel, delete the Text and pick an appropriate Icon. All of the Icons for Experience Builder Widgets are in the Brand And Logos page of the Icon Picker. Hint: there's a sneaky dropdown menu in the Icon Picker. Look carefully.

JeffreyThompson2_2-1749585725848.png

To make our icon bigger, turn on Advanced, open the Icon dropdown menu and type in a number. I went with 30px. Maybe a little too big for most applications, but its not outrageous. I changed the color to white using the box next to the size input and then opened the Background dropdown to set the Fill to blue.

JeffreyThompson2_3-1749586564223.png

In the Border dropdown, I set the color to a dark gray, picked a single line from the dropdown menu and set the thickness to 1px. You may not be able to see this border, but your brain does. Good borders are usually barely visible. To make it a circle, open the Border Radius dropdown and make it 50%.

JeffreyThompson2_4-1749587022098.png

In the Style Tab, Lock the Aspect Ratio at 100:100 and set the Width. I like the way 42px just barely cuts off the corner of the icon. It looks very dynamic to me.

JeffreyThompson2_5-1749587439238.png

Finally, in the Action Tab, add a Button Click > Widget Controller > Open Widget > Your Widget Action. (If you want this Button to link to something, that's in the Content Tab under Set Link.)

Edit: The June 2025 ArcGIS Online Update introduced the Toggle Widget Action, probably a better choice for this build.

Ugggh, that was a lot of work, do I have to do that for every Widget in my Widget Controller? Nope, hit the Duplicate Button. All you need to change is the icon and the target for the Action.

JeffreyThompson2_6-1749587857675.png

And we've got a set of Buttons that look a lot like a Widget Controller and work a lot like a Widget Controller but give you way more control over the design than a Widget Controller. And you can mix in a normal Button that will act like a Button, too.

JeffreyThompson2_7-1749588252682.png

...Until a hobbit throws your computer in a volcano, in a complex allegory for hubris and greed by someone who claims not to like or use any allegory or symbolism.

more
7 0 967
JeffreyThompson2
MVP Frequent Contributor

Before we get into the meat of today's post, let's clarify some terms. Both Experience Builder and the Maps SDK for JavaScript (or JavaScript API, if like me, you refuse to accept the name change) have things called Widgets. In both platforms, Widgets are blocks of reusable code designed to do some task that can be easily called in to an application by Builders. We will be discussing both types of Widgets today, so to make things a bit clearer Widgets in Experience Builder will be referred to as ExB Widgets and Widgets in the JavaScript API will be called JS Widgets.

In my opinion, one of the greatest selling points of Experience Builder Developer Edition is that anything in the JavaScript API, including JS Widgets, are readily available. So by firing up Experience Builder, I instantly get access to all the code that the Experience Builder team has made for me and, with a little more effort, all the code the JavaScript API team made for me. If, for example, I was disappointed that Experience Builder does not have a simple, cleanly designed, user-friendly way to switch between exactly two basemaps, I could create a Custom ExB Widget and call in the JS Widget that does the job. Calling in JS Widgets from ExB Widgets is a common programming pattern. In fact, if you look into the code, many of the OOTB ExB Widgets are little more than loaders of JS Widgets. It sure would be a problem for people making Custom ExB Widgets, if JS Widgets went away...

Hey, did you click that last link? Did you see that red rectangle?

JeffreyThompson2_0-1749042950337.png

It's deprecated. Every JS Widget is either already deprecated or is about to be. Starting next year, JS Widgets are going to start being Thanos snapped out of existence.

mr-stark-peter-park-infinity-war-gif.gif

Way back in the second most popular post on this Blog, my React primer, I noted that Experience Builder 1.13 would include Components, a new part of the JavaScript API better designed for working with frameworks like React that use a Virtual DOM, and that you should probably prefer to use Components over JS Widgets. Have I done that? Nope. And now it is official, Components are coming to kill JS Widgets. Better learn how to use Components. Hey, that's what this post is about. Are we finally getting to the point?

And now that I've wasted enough words that this post becomes legally copyrightable, like an online recipe, let's build a Basemap Toggle ExB Widget using a JavaScript API Component. I will start with some boilerplate code in widget.tsx:

import { React } from 'jimu-core'
import { MapViewManager, JimuMapView, JimuMapViewComponent } from 'jimu-arcgis'
import { Loading } from 'jimu-ui'
import reactiveUtils from 'esri/core/reactiveUtils'

const { useEffect, useState } = React

const Widget = (props) => {
	const viewManager = MapViewManager.getInstance()
	const mapView = viewManager.getJimuMapViewById(viewManager.getAllJimuMapViewIds()[0])
	const [jimuMapView, setJimuMapView] = useState<JimuMapView>(mapView)
	const [mapReady, setMapReady] = useState(false)

	useEffect(() => {
		if (jimuMapView) {
			reactiveUtils.whenOnce(() => jimuMapView.view.ready)
				.then(() => {
					setMapReady(true)
				}
			)
		}
	}, [jimuMapView])

	const activeViewChangeHandler = (jmv: JimuMapView) => {
		if (jmv) {
			setJimuMapView(jmv)
		}
	}	

	return (
		<div className='jimu-widget' >
			{
				props.useMapWidgetIds &&
				props.useMapWidgetIds.length === 1 && (
					<JimuMapViewComponent
						useMapWidgetId={props.useMapWidgetIds?.[0]}
						onActiveViewChange={activeViewChangeHandler}
					/>
				)
			}

			{mapReady ? 'map ready' : <Loading />}
		</div>
	)
}

export default Widget

 On it's own, this code doesn't really do anything. The net effect is to wait for JimuMapView to load, then save it to a variable and display the 'map ready' text. Let's breakdown exactly how we accomplish nothing with this code.

On the first render, the mapView is captured by the viewManager and stored into state as jimuMapView. It's actually a null value at this point. mapReady is given a default value of false. Somewhere about this point, the map starts to load, triggering the onActiveViewChange property of the JimuMapViewComponent.

One thing that frequently confuses developers is that the onActiveViewChange property only fires when the entire mapView object changes. As in, the Map Widget contains two maps and the user switches between them. For an example of someone not quite getting this concept, you can look at the official using map components example, which requires having two maps in the Map Widget and the end-user to swap between them before the Legend and Map Layers will actually load.

The onActiveViewChange property calls the activeViewChangeHandler function that sets jimuMapView to the actual mapView object and triggers render number two. Because jimuMapView has changed from null to a truthy object, the useEffect function fires on the second render. useEffect and the activeViewChangeHandler functions also started on the first render but their if clauses prevented them from doing anything. At this point, jimuMapView is truthy, but it is a very complex object and may not actually be fully loaded, so reactiveUtils is called to wait a little bit for the map to actually be ready. And when jimuMapView says it's really, actually ready this time, the mapReady value is set to true, triggering render number three.

Theoretically, the ExB Widget has been showing a loading graphic through the first two renders, but they have actually happened faster than Loading can load and now that mapReady is true the ExB Widget should be showing text saying 'map ready'. And that was a Shakespearian amount of ado about nothing. Isn't React fun? Now that we've got the code to load the map without crashing, we can start adding the functional bits.

In the import statements, I'll add this:

//Before 1.19
import { ArcgisBasemapToggle } from '@arcgis/map-components-react'
//In 1.19, use this instead
import 'arcgis-map-components'
//Works in either version
import Basemap from 'esri/Basemap'

I change the ternary in the return statement to this:

//Before 1.19
{mapReady ? <ArcgisBasemapToggle id='basemapToggle' /> : <Loading />}
//In 1.19, use this instead
{mapReady ? <arcgis-basemap-toggle id='basemapToggle' /> : <Loading />}

And add this block between the activeViewChangeHandler and the return:

const toggle = document.getElementById('basemapToggle')
if (toggle) {
	toggle.componentOnReady().then(() => {
		toggle.referenceElement = jimuMapView
		toggle.nextBasemap = new Basemap({
			portalItem: {
				id: 'id'
			},
            thumbnailUrl: 'url'
		})
	})
}	

Assuming I have entered the correct values for id and thumbnailUrl, this Widget should now be fully functional. Let's talk about what this code does.

The code asks the browser to find the Basemap Toggle Component by the id we gave it. On the first two renders, the browser won't be able to find it because it doesn't exist yet. On render three, it will exist, toggle will become truthy and we will enter the if statement. If you console log toggle, you will find it is a DOM node, but it can also be treated as a JavaScript Object, functionally the same as a JS Widget. I don't really understand what quantum mechanics trickery is going on here, but it does work and you will see many examples like this if you look at the Components documentation. We will choose to believe that the cat is alive and collapse the waveform with toggle as a JavaScript Object.

TypeScript will claim everything inside this if statement is impossible. TypeScript is often right about things, but not today. You can just ignore TypeScript if you don't like what it says, if the Widget doesn't crash, then you were probably doing something legal after all. The first thing TypeScript doesn't believe in is the componentOnReady() method. This method is on every Component and it tells the code to wait for the Component to fully load before proceeding with the rest of the function. By my count, this is the fourth time we have asked the browser to slow down and wait in the past 100 micro-seconds, making it only slightly more patient than my four-year-old.

Now inside the then() statement, toggle is ready to receive further instruction. We will set the referenceElement property to jimuMapView. This tells the toggle what map to toggle. The nextBasemap property is the basemap it should toggle to. The toggle also has an activeBasemap property, but we don't need to worry about setting that, toggle will pull it from jimuMapView automatically. For ease creating a Settings Panel, I am making my nextBasemap from a Portal Item. In testing, I found that the thumbnail image will not load until the toggle is clicked, unless a thumbnailUrl is specifically added, so I'm doing that as well.

If I was making this Widget as a one-off, I could stop here, but I want to make this re-usable, so we'll build a Settings Panel next. Here is some boilerplate for setting.tsx:

import { React } from 'jimu-core'
import { AllWidgetSettingProps } from 'jimu-for-builder'
import { MapWidgetSelector } from 'jimu-ui/advanced/setting-components'

const Setting = (props: AllWidgetSettingProps<any>) => {

    const onMapWidgetSelected = (useMapWidgetIds: string[]) => {
        props.onSettingChange({
            id: props.id,
            useMapWidgetIds: useMapWidgetIds
        })
    }

    return (
        <div className="widget-setting">
            <MapWidgetSelector
                useMapWidgetIds={props.useMapWidgetIds}
                onSelect={onMapWidgetSelected}
            />
            <p>This widget id: {props.widgetId}</p>
        </div>
    )
}

export default Setting

Not much to say about this code, it just lets Builders tell this Widget what Map Widget it should work with. I also like to show props.widgetId in the Settings Panel of all my Widgets. I don't have any specific need for it in this Widget, but it's useful information that ESRI doesn't want you to have. I have been known to temporarily add one of my Widgets to a project, just so I can figure out the id of an ESRI Widget, usually a Sidebar.

Now the functional bits, in the imports:

import { TextInput, Label, TextArea } from 'jimu-ui'

Between onMapWidgetSelected and return:

const handleBasemapId = (e) => {
    props.onSettingChange({
        id: props.id,
        config: props.config.set('basemapId', e.target.value)
    })
}

const handleThumbnailUrl = (e) => {
    props.onSettingChange({
         id: props.id,
         config: props.config.set('thumbnailUrl', e.target.value)
    })
}

In the return statement:

<Label
    className='w-100'
>
    Portal Item Id Of Other Basemap:
    <TextArea
        defaultValue={props.config.basemapId}
        onChange={(e) => handleBasemapId(e)}
    />
</Label>
<Label
    className='w-100'
>
    Thumbnail Url Of Other Basemap:
    <TextInput
        defaultValue={props.config.thumbnailUrl}
        onChange={(e) => handleThumbnailUrl(e)}
    />
</Label>

I also need to change config.json to this:

{
  "basemapId": "",
  "thumbnailUrl":  ""
}

 I also need to go back to widget.tsx and change that if statement we looked at earlier to this:

if (toggle) {
	toggle.componentOnReady().then(() => {
		toggle.referenceElement = jimuMapView
		if (props.config.basemapId) {
			toggle.nextBasemap = new Basemap({
				portalItem: {
					id: props.config.basemapId
				}
			})
			if (props.config.thumbnailUrl) {
			        toggle.nextBasemap.thumbnailUrl = props.config.thumbnailUrl
		        }
		}
	})
}

The settings.tsx allows Builders to enter an id and thumbnailUrl for the basemap they want to add. With onSettingsChange() being a built-in method for turning typing in the Settings Panel into data stored in the config.json in the server files. The changes in widget.tsx are designed to grab the stored values from the config.json file and use them in the Widget and the if statements are designed to prevent the Widget from crashing when/if the data is missing.

That pretty much does it. We built an ExB Widget using Components instead of JS Widgets, but since you all waited patiently through my story, how about a treat? Here's a Basemap Toggle Widget that probably won't crash next year.

Edit: It didn't break next year, at least not yet. It broke this year. The way to import Components changed in Developer Edition 1.19. See the 1.19 version comments in the code blocks above to fix this Widget.

Edit 2: Upon further review, there is a race condition between this Widget loading in memory vs. it's DOM representation. In 1.19, it appears to get into memory much faster than it makes it to the DOM and so fails to reliably load. I hope there is a better way to do this, but a recursive function call using setTimeout() does appear to load more reliably.

const prepToggle = (attempts=0) => {
	setTimeout(() => {
		const toggle = document.getElementById('basemapToggle')
		attempts++
		if (toggle) {
			toggle.componentOnReady().then(() => {
				toggle.referenceElement = jimuMapView
				if (props.config.basemapId) {
					toggle.nextBasemap = new Basemap({
						portalItem: {
							id: props.config.basemapId
						}
					})
					if (props.config.thumbnailUrl) {
						toggle.nextBasemap.thumbnailUrl = props.config.thumbnailUrl
					}
				}
			})
			return
		} else if (attempts === 20) {
			return
		} else {
			return prepToggle(attempts)
		}
	}, 500)
}

prepToggle()

This function is uses setTimeout() to wait half a second, then it attempts to find the Basemap Toggle Component and give it the necessary properties. If it doesn't, it calls itself again. The attempts variable is designed to break the loop if the Component never loads.

more
4 1 925
220 Subscribers