Experience Builder Tips and Tricks

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

Latest Activity

(73 Posts)
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 417
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 334
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 653
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 659
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
6 0 645
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:

import { ArcgisBasemapToggle } from '@arcgis/map-components-react'
import Basemap from 'esri/Basemap'

I change the ternary in the return statement to this:

{mapReady ? <ArcgisBasemapToggle 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.

more
4 0 556
JasonBOCQUET
Frequent Contributor

Hello everyone,

This post will follow on from the previous one I wrote. (https://community.esri.com/t5/experience-builder-tips-and-tricks/how-to-easily-connect-your-data-and...)

The aim is to be able to filter a first data source (transactions, for example) so that, thanks to a common identifier present in each of the tables, the other data sources (properties, offers, assignments) present in other widgets (Map, List, Table, Graph) are updated. All this without having to duplicate columns in each table concerned or select items on a map to bypass the system.

Last time, I mentioned the difficulty that ArcGIS Experience Builder had in offering dynamic rendering between several widgets with different data sources.
Indeed, if I want to filter my data according to criteria linked to transactions, and have a map rendering that shows me the buildings linked to these transactions, I must add the fields that I use to filter my transactions to my Building table.

In this way, the data I display in my application about buildings is updated according to the transactions I've filtered.
But this process isn't easy to set up and requires a lot of changes to be made to our databases that aren't normally necessary.

Since this post, there's been nothing new on the ESRI side, and no update along these lines, so I had to get my brain working at full speed to find a way of cobbling together something that would work.

So I concentrated on the way widgets currently work: it's possible to set actions on our data. For example, we can add an action when items are selected and only then can we give the order to filter the data records that have been selected. This filtering is done using action parameters, creating a link between two different data sources (one triggering, and one ‘undergoing’ the action) using a common identifier.
So let's suppose that we're filtering a ‘Transaction’ data layer according to the years in which the transactions were signed, and that I don't have a replica of the ‘Transaction year’ column in my ‘Building’ data layer. I want to see the transactions for 2021 and therefore the buildings associated with these transactions on a map.

 

If I'm doing things using a ‘Modification of record selection’ action and if you followed my first post, this means that once I've filtered my transactions, I have to make a selection on the map by hand in order to filter the buildings.
Otherwise, I need to have added the ‘Transaction Year’ column to my Building layer beforehand for the Group Filter to work, but this solution is not possible if we have an N-1 relationship between our data*.

*the Transaction-Building relationship is N-1, there are N transactions for 1 building, which means that if I add the ‘Transaction Year’ column to the Building table, I'll have to ‘clone’ each building for each transaction involving that building, otherwise I'll lose information. And clearly, cloning buildings sucks because in terms of cartographic rendering it means having N points superimposed...


With that in mind, I was left with only 2 solutions:

  • Pray that ESRI will finally develop an action parameter that is triggered not when you SELECT something, but rather when you FILTER something
  • Succeed in creating a SELECTION action, without the user having to do it himself.

 

As you can imagine, I had to focus on the second solution.

The idea was simple: what if I used the Selection tool to simulate a Selection action without the user realising?

So we're going to take a Selection Widget and choose ‘Select according to attributes’ as the source. Then click on ‘New data’. To follow my example, I'm going to choose my data source ‘Transactions’ (in my case it's a simple Table), thanks to the SQL expression generator, I'll be able to set up Filters that will be used to select the data according to attributes (I'm using several fields with the ‘AND’ condition).

Once that's done, all that's left is to set up actions when there's a Modification of record selections. This action is set up with ‘Structure’ as the target, then ‘Filter data records’ is selected and all that's left is to choose the Building source (or any other source) which has an identifier in common with the transactions (in my case we have an ID called ‘ID_LP’).

The final result is as follows:

JasonBOCQUET_0-1746607140587.png

As you can see, we ‘disguise’ this Selection widget as being a sort of Filter widget, and thanks to this, I can filter my transactions according to using fields that are not present in any other table or entity layer AND I manage to filter my other cascading data sources. Something that used to be impossible.
The other advantage is that, because we've set up our actions so that the data records are filtered, it doesn't show up, either on the map rendering or even in a Table or List Widget. There's no big highlight.


Of course, you have to bear in mind that this technique has its limits:

  • Even if there aren't any lines highlighted in blue or Highlight points in neon yellow, you're still selecting data, so if you make a selection by hand in addition, or click on an item, the widget can quickly find itself no longer knowing who the source of the selection is. For optimum use, remember to click on ‘Delete selection’ if you wish to make another type of selection, to avoid conflicts.

 

  • Let's say you want to offer a view of the contents of the Transactions table. You integrate a Table widget so that the user can see the contents of the table. Be very careful with this: if you don't set any filter actions, you will only select the transactions in the table that you have filtered (logically). But if you set up a filter action, you have to do so by setting the same source (i.e. transaction & transaction) as the action's trigger and target. Well, by doing this, you're going to bug the filters in the Selection widget, which will no longer be able to be modified without first deleting the current selection.
    Here's what I recommend to get round this little problem: if you want to display tables, maps or other widgets relating to the data source you've used in the Selection tool, duplicate this layer/table for the other widgets. By doing this, you're querying ANOTHER data source (which is actually the same one) and you can set up your filter action to filter the records without bugging the filters in the Selection tool.


I think I've come to the end of this tip, so I hope it's helped you. This solution is really in the ‘do-it-yourself’ category, but at least it has the merit of being able to resolve certain situations.
I'm still hoping that ESRI will one day come up with a solution for this, because I think it's a real shame that in such a powerful GIS tool you can't manage relationships between several data sources by simply using a common ID... something that's been done since the dawn of time in lots of other software.

 

Gone°

more
1 1 812
JeffreyThompson2
MVP Frequent Contributor

A creeping contagion is taking over the ESRI ecosystem. Every update it swallows a little more. Soon, it will devour everything leaving nothing in its wake. The name of this virus is Calcite and it is coming for your CSS. Once Calcite swallows something all your CSS hacks will break as the Shadow DOM and infinite wrappers surround and subsume your target. Calcite will infest everything. We are powerless to stop it. It is different and I am instinctually fearful of change. However, hope is not yet lost, we may not be able to stop Calcite, but we can adapt it. 

(Actually, there are two creeping contagions taking over ESRI, but Components are a problem for next year.) 

As I upgraded to Developer Edition 1.17, I found that the Map Layers Widget was the latest victim of Calcite and my custom font added in the Theme was no longer being respected. The Map Layers Widget occupies a very prominent space in my overall design, so the font change was very noticeable and distracting. And Calcite was blocking my typical CSS targeting attacks. So, I did something unthinkable. Something I hoped I would never have to do. I learned about Calcite and CSS variables.

First, I will show you my solution. Then, I will explain why it works. In the style.scss of my Theme, I added this...

:root {
    --calcite-font-family: Relish Pro Medium,"Avenir Next",Avenir,"Helvetica Neue",sans-serif;
}

The :root CSS selector is the default CSS settings of the page, so altering :root will change everything. Using -- is how you declare or alter a CSS variable. Calcite variables are written like --calcite-variableName, with font-family being the specific variable I am changing. After the colon is a list of fonts that the page will attempt to use in order. I've put my custom font, Relish Pro Medium, at the start of this list making it the default Calcite font for my application. For the rest of the list, I used my browser's Dev Tools to find and copy the Calcite defaults, so if Relish fails for some reason, it will follow the standard Calcite backups.

That's all it took. Fight Calcite with Calcite and change the Calcite variables to better fit your needs.

more
0 3 478
JeffreyThompson2
MVP Frequent Contributor

You turned off updating and deleting in a Feature Layer. You put an Edit Widget in Experience Builder and what's that Delete Button doing there? And it works, too?

Two important questions:

  1. Do you own the data layer?
  2. Are you an Admin on your ArcGIS Online/Enterprise Portal?

If you answered yes, to either of these questions, that's a quirk of the ESRI ecosystem. It's not just limited to Experience Builder. If you own a data layer or you're an Admin, you can always do whatever you want to the data even if it's not allowed for other users. It's on one hand a very sensible and on the other very poor design choice by ESRI. Afterall, if you are an Admin, you may need to delete some bad data maybe even against the will of the data owner, but being an Admin doesn't make you immune from "Oops, wrong button syndrome". Try logging in as some other user and the Delete Button should be gone.

If you're not an Admin or a data owner, contact ESRI Support. Something is very wrong.

Edit: Here's an official quote about this issue from the JavaScript API documentation.

Authenticated users that are layer owners, administrators or users with full editing privileges will have their elevated user privileges applied in regards to editing behavior and data access. This mimics the behavior available in Map Viewer. To opt out, set esriConfig.userPrivilegesApplied to false.

Note that last line. If you are on Developer Edition, there is a way to opt out of your elevated powers.

more
3 4 628
JeffreyThompson2
MVP Frequent Contributor

Last week, I traveled to the ESRI Developer and Technology Summit in Palm Springs, California. I learned/re-learned/experienced a lot of stuff between getting off the plane to the airport bar on the way back. Here are my notes. Some of them are about Experience Builder, some are more general web development stuff, some are about other ESRI products and some are about Palm Springs and the conference itself. This is just going to be a bunch of one liners and don't expect me to elaborate in the comments. I don't have many details on much of this stuff myself. Ordinarily I try to cite my sources on this blog, but for practical and confidentiality reasons, I'm keeping stuff anonymous this time. There were a number of improvements I spoke to ESRI staff about. I'll be tagging these with YCTML (you can thank me later), so you know I am solely and personally responsible for making this stuff happen when and if it does. Unless you don't like this stuff in which case I really had nothing to do with any of it. 

I can't do a post like this without showing my stupid face, so here you go. I'm on the right. My new bestie @SimonSchütte_ct is on the left. The guy in the middle is Jack "What the Internet Would Name a Volcano" Dangermond.

PXL_20250311_014822731.MP-ANIMATION.gif 

Experience Builder Stuff

  • I successfully convinced with a rigorous intellectual argument the Build Team that the Clear Map Highlighting Button is in a very bad place, YCTML.
  • I successfully emotionally manipulated the Build Team into getting the new Turn On/Off All Layers Buttons to respect the customization in the Map Layers Widget. YCTML, we're getting native support for thematic groups.
  • If you want to allow your users to print an entire Page, for say creating a custom report, the Button Widget can link to Print Preview.
  • Windows can be reused multiple times throughout an application and called from any Page.
  • For best results, design based on multiples of 16px.
  • Place a Column Widget inside a Sidebar Widget and add some Padding for a neat floaty effect.
  • Having trouble navigating around a complicated layout? Use these carrot things at the bottom of the Builder.JeffreyThompson2_0-1742399901364.png

     

  • Need to add an npm package to a Custom Widget? Create a package.json within the file structure of the Widget and call npm i on that folder.
  • Don't change the version number when upgrading a Custom Widget to a new version of Experience Builder.
  • Stop and restart the client server when first creating a new Custom Widget.
  • The Python API is capable of transferring an Experience Builder project between Portals.
    • It can handle remapping of Webmaps and Datasources.
    • But, as of now, it will break if you have any Custom Widgets.

General Web Stuff

  • Plan before you build.
  • User Testing
    • Make a scenario for your end-users to test. Write them a story. Give them a character. Dress in Elizabethan costume. Ok, maybe not that last one.
    • It doesn't take a lot of testing to find most problems.
      • If a user can successfully make the first click on a task, they will complete the task 86% of the time.
      • Five test users can find 80% of usability issues.
    • My notes say "question your end-user's goals." I'm pretty sure that means ask them what they want to accomplish, not belittle their worthless dreams, but you do you.
    • Watch and take notes as your users test stuff, but resist the urge to tell them how to do stuff.
      • If you can find a sneaky way to watch them work without telling them you made the app, even better.
      • Assure your users that you are testing the dumb application, not their dumb selves.
    • Classify your problems based on severity, not frequency and assume any issue will be worse on the live application than in testing.
  • Some types of applications, like how to get help in an emergency, can instantly go from zero users to thousands. Make sure your servers can handle that kind of jump.
  • Do you have a design with a list next to a map? (Something similar to the JewleryBox Template in Experience Builder.) That design doesn't work on a phone. Instead use a "two-page" list on one page, map on the other layout for phones.
  • ESRI Webmaps will not pass accessibility testing, at least for now, but if you can convey the same information some other way, like a list, then the map becomes more "decorative, than functional."

Other ESRI Stuff

  • Coming Soon to (or maybe already in) an ArcGIS Pro Near You
    • Create a Utility Network from a Feature Class.
    • Automatically turn a Geometric Network into a Utility Network.
    • Pre-trained AI models that tell you why they class stuff the way they did.
    • AI Arcade Coding Assistant.
    • Estimate Time To Event will tell you the exact day your bridge will fall down.
    • DIY-AI extensions to the AI Assistant.
  • ArcGIS Online/Enterprise
    • I talked to several members of the Online staff about building a button to send an email to the members of a Group. I could put YCTML here, but it seems like they have been asked so many times that I was a few seconds away from a punch to the face.
    • Did you run a Credit report on your ArcGIS Online organization? Was your biggest user No Username? That's storage.
      • They say they are going to make the Credit Reports better, in a vague nebulus way.
    • ArcGIS Enterprise 11.6 will be released...never. The version after 11.5 will be called Enterprise 12.0.
      • The main reason for the new version number is the retirement of all the JavaScript 3.X stuff, like WebAppBuilder.
  • ArcGIS JavaScript API
    • Take a look at this Demo to see how to make a shapefile into a FeatureLayer.
    • I spoke with one staff member who said the saveAs() function can be used to create a new Portal Item from a client-side FeatureLayer.
      • But the documentation disagrees.
      • I am following up on email about this. Update: I have confirmation that the documentation is correct. I have opened an Enhancement request and dropped a new Idea.
      • I guess, YCTML, if this isn't supported and it spirals into an actual function.
      • If it is a function, I may take a stab at a FeatureLayer Maker Widget.
    • The hitTest() function and the selectFeatures() function built on top of it will allow for developers to set the search radius rather than its current fixed 6px, YCTML.
    • I overheard some staff members discussing building an Interactive Legend Widget. Assuming those guys build it, expect it to flow into Experience Builder eventually. Which leads me to...
  • Instant Apps
    • Instant Apps have their own Component Library out on a Public GitHub Repo that you can totally just use if you want.
      • That Interactive Legend Component looks fun.
      • The Instant Apps Team can't think of a reason you couldn't hack one of their Components into Experience Builder.
      • I think I may have to try that.
    • There is no Developer Edition for Instant Apps or Dashboards.
      • But if you ask the Instant Apps Team nicely, they will send you the code for any Instant App you want.
      • And if it becomes a thing, YCTML.
  • ArcGIS Solutions

Other Stuff

  • Palm Springs Tramway
    • When I stepped onto the Tram, it was 80 degrees in the desert.
    • When I stepped off the Tram 10 minutes later, it was 40 degrees with a foot of snow on the ground.
    • Closest thing to a closet to Narnia I have ever experienced.
    • No matter what Van Halen says, do not jump on the gondola.
  • Chew thoroughly before swallowing.
  • Congratulations to @RasterFan98 for getting the Custom Widgets Group into the Plenary Session.
  • If you ask the ESRI Events staff for a telescope to view the lunar eclipse during the Summit Party a few days before the conference, they will be disappointed they could not make it happen.
  • I attempted to fill my time attending every possible talk I could.
    • In retrospect, I wish I blocked out at least an hour a day to spend on the Expo floor, as most of the things I learned and accomplished happened outside of the tech sessions.
    • And many of the talks were also recorded.
  • If you uncover a massive conspiracy that aligns with your values and goals, is it your moral duty to still expose the truth?
  • NATO is investigating reports by German Intelligence that the Nord Stream Pipeline was sabotaged by ....
    • NATO apparently thinks they can show a lolz so random spot in the Baltic Sea to a room full of map nerds and no one would know what it was about.
  • ESRI Events staff makes some pretty good food.
    • Thursday's lunch was probably the best meal I have ever had in a high volume cooking situation.
    • If someone can get me the recipe for that quinoa salad, I might eat some quinoa again. 
  • Why didn't you Dooooooooooodge?
  • Mapillary - Strap a camera on something and make your own version of Google StreetView, for free, according to my source.
  • No one likes the sound of their own voice.
  • @KenField gets to go to DevSummit, but not @JohnMNelson. Is it because Ken is a public figure?
  • There is apparently a set music playlist that ESRI uses before the Plenary/Keynote Session everyday. Inexplicably, Maps by the Yeah Yeah Yeahs is not on it.
  • Palm Springs is a pretty town. I see why the celebrities used to hang out there. Here's a sunrise rainbow on a mountain from the Conference Center.eedcc675-441f-4ba4-8af0-e4dca527287c~1.jpg
  • The Palm Springs Airport is mostly outdoors.
    • Neat when I swiftly walked through it on a perfect weather day.
    • Not so neat when I had to wait there for three hours in very bright sun with a strong, chilly wind.
    • Considering the length and intensity of the Palm Springs summer, I think there are probably more not so neat than neat days for this concept.
  • The Big Kahuna Burger just sounds better with cheese. 
  • The face of a vicious barbarian.JeffreyThompson2_0-1742482907472.png

     

more
15 1 879
210 Subscribers