ChangeWebMap Widget

475
5
03-21-2025 08:43 AM
Labels (2)
LanceCole
MVP Regular Contributor

I am looking for some direction on creating a custom widget in Experience Builder.  I have worked with Application Builder for years but never ventured into the ExB arena.   About 6-7 years ago I created a Load Map widget based on the City of Garland, Texas ChangeWebMap Widget.  I have kept the widget updated; however, now must move on to ExB to continue its use.

I believe I can start with:

  1. ESRI List or Fixed Panel widget
  2. Add code to query the enterprise portal for a list of Maps, map IDs, name, etc. from a particular group
  3. Use the data to dynamically populate the list or add cards to the fixed panel
  4. Add code to change the application/Map webmap ID and refresh on click of a list item or card

I am able to accomplish this using the application ID and webmap ID as URL parameters but I am struggling find how to programmatically achieve this in ExB.

Can anyone point me to where in ExB and/or examples to:

  1. query a portal for the maps in a designated group
  2. dynamical add items to a list or fixed panel
  3. change or set the wedmap ID on on the app and refresh

If we only had a few maps they could just be added to the app map references and toggle them from the application using available widgets.  However, we currently have 10-15 maps we want to have available and this number is going increase.  We also have periodic maps that need to be quickly added and removed.

Any help would be appreciated.  I feel as though I am facing a vertical learning curve at the moment as ExB custom widgets are a totally different beast.

0 Kudos
5 Replies
JeffreyThompson2
MVP Frequent Contributor

https://developers.arcgis.com/experience-builder/storybook/?path=/docs/components-jimu-ui-basic-item...

The Item Selector in the Storybook might get you most of the way done.

GIS Developer
City of Arlington, Texas
LanceCole
MVP Regular Contributor

@JeffreyThompson2 , 

Thanks for the quick reply and that does look promising for dynamically populating a list of maps from a group.  Still working on where the loaded map would be changed and how to refresh.

We can generate a URL with the application and webmap IDs and use it as a link in the Item Selector cards, but I really would like to do that within the widget to hide the ID information.  The URLs are not pretty:

https://my.gis.com/portal/apps/experiencebuilder/experience/?

id=fc4f1eb6a36342c9b0264a02109024a7&

webmap=1cf42d227f4d34a08cacfed55918f966

The first part of the URL can be cleaned up using a proxy but the rest would need to added in the request header by the widget.

0 Kudos
MattiasEkström
Frequent Contributor

@LanceCole 
I've been thinking about this a bit too. In our current WAB solution we have different applications for the different web maps and I created a simple widget to switch between them and keep the current map scope. In our upcoming ExB solution I would prefer to have just one application to maintain and be able to switch web maps, but I've just started looking at the dev edition and have no idea yet.

But I've worked a bit with OOTB ExB and one of the big differences is that you can have multiple web maps and you have to configure which map to use in map centric widgets. I'm afraid this could be a problem, and all map centric widgets break when you change the web map. Do you have any experience with this so far?

0 Kudos
Vara_PrasadM_S
Frequent Contributor

Hi,

I am also trying for similar requirement. I tried below approach and could able to create a new instance for JimuMapView with new web map id. However, the new instance is not sent to all widgets and app. I am unable to identify how can we do this. I used 'getAppStore().dispatch(appActions.jimuMapViewUpdated' but it did not work. Any guidance would be very much helpful.

const createNewJimuMapView = async (jimuMapView) => { 
  const dataSourceManager = DataSourceManager.getInstance();
  const dSources = dataSourceManager.getDataSourcesAsArray()

  const dsOptions = { 
    id:  "ds_11e0c122b7c745d4ae1385ae907733b0",
    itemId: "11e0c122b7c745d4ae1385ae907733b0",
    portalUrl: "<Portal Url>",
    sourceLabel: "test",
    type: "WEB_MAP"
  }

  const ds = await dataSourceManager.createDataSource(dsOptions)

  //jimuMapView.destroy() //tried destroying, it destroyed existing

  const sourceMap = new WebMap({
    portalItem: {
      id: '11e0c122b7c745d4ae1385ae907733b0'
    }
  });

  await sourceMap.load();
  const mapView = new MapView({
    map: sourceMap
  })

  let options = {} as JimuMapViewConstructorOptions
  options['mapWidgetId'] = jimuMapView.mapWidgetId
  options['isActive'] = true
  options['dataSourceId'] = ds.id
  options['mapViewManager'] = MapViewManager.getInstance()
  options['view'] = mapView
  options['isEnablePopup'] = true

  let newJimuMapView = await MapViewManager.getInstance().createJimuMapView(options)
  const newJimuMapViewInfo: JimuMapViewInfo = {
    dataSourceId: ds.id,
    id: newJimuMapView.id,
    isActive: true,
    mapWidgetId: newJimuMapView.mapWidgetId,
    status: JimuMapViewStatus.Loaded
  }
  getAppStore().dispatch(appActions.jimuMapViewUpdated(newJimuMapView.id, newJimuMapViewInfo as IMJimuMapViewInfo))
  return newJimuMapView;
};

 

Vara_PrasadM_S
Frequent Contributor

Hi @JeffreyThompson2 , Could you please throw some light on this. How can I make my code work?

Thanks in advance.

0 Kudos