Select to view content in your preferred language

Making runtime featureLayers register as datasources for select widget

258
6
Jump to solution
05-15-2024 01:15 PM
JeffreyThompson2
MVP Regular Contributor

I am loading my map layers at runtime through a custom widget. Everything is configured as desired in Developer Edition 1.12. Now, I am upgrading to 1.14 primarily for the access to the Select Widget and the Add to Table Data Action.

Adding a data layer with the OOTB Add Data widget will make the layer selectable in the Select Widget, but layers loaded from my custom widget are not available in the Select Widget.

How can I get the Select Widget to recognize the added data? Bonus points, if the Map Layers Widget will also show the Add To Table option.

@WeiYing1 Would creating a client side data source be picked up by the Select Widget? https://github.com/Esri/arcgis-experience-builder-sdk-resources/tree/master/widgets/client-side-outp... Can a single widget have multiple output datasources?

Looking through the code for the Add Data Widget I found these lines.

const dataSourcesChangeMessage = new DataSourcesChangeMessage(widgetId, DataSourcesChangeType.Create, dataSources)
MessageManager.getInstance().publishMessage(dataSourcesChangeMessage)

Could publishing a message similar to this trigger the Select Widget to find the layers?

GIS Developer
City of Arlington, Texas
0 Kudos
2 Solutions

Accepted Solutions
Yueyang_Li
New Contributor III

@JeffreyThompson2  You can generate multiple output data sources in your widget. If you do not know the number and schema of the data sources your widget needs to generate in your settings, I recommend you look through the Add Data widget.

Please see the createDataSourcesByDataOptions method in the add-data/src/runtime/utils.ts

1. Prepare the FeatureLayerDataSourceConstructorOptions. Pass the layer to let the created data source query via it. The layer can be client-side or server-side Maps SDK feature layer. Pass the dataSourceJson to let the data source manager know the definition of the data source, including id, type, labelurl, itemId, portalUrl, layerId (e.g. '0', '1') and geometryType (e.g. 'esriGeometryPoint', 'esriGeometryPolyline').

2. Create data sources by DataSourceManager.getInstance().createDataSource(options).

3. Publish the message you mentioned above if you want the add-to-map, pan-to, and zoom-to message actions of the map widget (also need to declare your widget publish messages in the manifest, by adding "publishMessages": ["DATA_SOURCES_CHANGE"]). If you only need data actions, you do not need to do it.

 

View solution in original post

JeffreyThompson2
MVP Regular Contributor

The DataSourcesChange message did not work, but I got something functional with the JimuMapView.addRemoveDataOnMap() method.

 

 

setTimeout(() => {
				console.log(mapLayer.sourceJSON)
				const data: DataSourceJson = {
					id: 'custom_' + layerGroup.layers[i].id,
					layerId: `${mapLayer.sourceJSON["id"]}`,
					itemId: layerGroup.layers[i].id,
					url: layerGroup.layers[i].url,
					type: 'FEATURE_LAYER',
					geometryType: mapLayer.sourceJSON["geometryType"],
					label: mapLayer.title,
					portalUrl: 'url'
				}
				const dataJson = Immutable(data)
				const dataSourceOptions = {
					id: layerGroup.layers[i].id,
					layer: mapLayer,
					dataSourceJson: dataJson
				}
				
				console.log(dataSourceOptions)
				const dataSource = DataSourceManager.getInstance().createDataSource(dataSourceOptions)
				dataSource.then((source) => {
					
						console.log(source)
						const sourceId = source.id
						const addMapData: AddToMapData = {
							mapWidgetId: 'widget_9',
							messageWidgetId: 'widget_33',
							jimuMapViewId: jimuMapView.id,
							dataSourceId: sourceId,
							type: ActionType.MessageAction,
							title: 'Add Data',
							dataChangeType: DataChangeType.Create,
							dataChangeStatus: DataChangeStatus.Fulfilled
						}
						console.log(addMapData)
						mapDatas[sourceId] = addMapData
						
					
					setTimeout(() => {
						jimuMapView.addOrRemoveDataOnMap(mapDatas)
					}, 50)
				})

}, 3000)

 

GIS Developer
City of Arlington, Texas

View solution in original post

0 Kudos
6 Replies
WeiYing1
Esri Contributor

@TonghuiMing any comment on this question?

0 Kudos
JeffreyThompson2
MVP Regular Contributor

I've thought about and researched this question the best that I can over the past month and I keep coming back to the same issue. I need to take the REST endpoint of a FeatureLayer and have it be recognized by Experience Builder as a valid datasource. I know Experience Builder is capable of this, but I don't know how to do it.

I've looked at the sever/client side data source widget samples, but they presuppose an already existing datasource to create from. https://github.com/Esri/arcgis-experience-builder-sdk-resources/tree/master/widgets/server-side-outp...

My widget would also need to output an arbitrary number of datasources which presumably the Add Data Widget is capable of, but is not shown in any code samples. 

GIS Developer
City of Arlington, Texas
Yueyang_Li
New Contributor III

@JeffreyThompson2  You can generate multiple output data sources in your widget. If you do not know the number and schema of the data sources your widget needs to generate in your settings, I recommend you look through the Add Data widget.

Please see the createDataSourcesByDataOptions method in the add-data/src/runtime/utils.ts

1. Prepare the FeatureLayerDataSourceConstructorOptions. Pass the layer to let the created data source query via it. The layer can be client-side or server-side Maps SDK feature layer. Pass the dataSourceJson to let the data source manager know the definition of the data source, including id, type, labelurl, itemId, portalUrl, layerId (e.g. '0', '1') and geometryType (e.g. 'esriGeometryPoint', 'esriGeometryPolyline').

2. Create data sources by DataSourceManager.getInstance().createDataSource(options).

3. Publish the message you mentioned above if you want the add-to-map, pan-to, and zoom-to message actions of the map widget (also need to declare your widget publish messages in the manifest, by adding "publishMessages": ["DATA_SOURCES_CHANGE"]). If you only need data actions, you do not need to do it.

 

JeffreyThompson2
MVP Regular Contributor

Thanks to your suggestions I have a block of code that completes without error and the DataSourceManager indicates that the layers have been accepted as valid datasources. However, the Select Widget still does not acknowledge them and the full list of data actions is not visible.

mapLayer = new FeatureLayer({
				url: layerGroup.layers[i].url,
				id: layerGroup.layers[i].id
})




setTimeout(() => {
				console.log(mapLayer.sourceJSON)
				const data: DataSourceJson = {
					id: 'custom_' + layerGroup.layers[i].id,
					itemId: layerGroup.layers[i].id,
					url: layerGroup.layers[i].url,
					type: 'FEATURE_LAYER',
					geometryType: mapLayer.sourceJSON["geometryType"],
					label: mapLayer.title
				}
				const dataJson = Immutable(data)
				const dataSourceOptions = {
					id: layerGroup.layers[i].id,
					layer: mapLayer,
					dataSourceJson: dataJson
				}
				
				console.log(dataSourceOptions)
				const dataSource = DataSourceManager.getInstance().createDataSource(dataSourceOptions)
				dataSource.then((source) => {
					//map layers widget
					const messageLayer = new DataSourcesChangeMessage('widget_30', DataSourcesChangeType.Create, [source])
					MessageManager.getInstance().publishMessage(messageLayer)
					//select widget
					const message = new DataSourcesChangeMessage('widget_63', DataSourcesChangeType.Create, [source])
					MessageManager.getInstance().publishMessage(message)
				})
				console.log(DataSourceManager.getInstance())
}, 3000)

Console log of DataSourceManager.GetInstance()

JeffreyThompson2_0-1720192482778.png

The only actions I am getting are the same ones I saw adding the layers to the map using the JS SDK methods.

JeffreyThompson2_1-1720192866760.png

I have added the publishMessgaes statement to my manifest.json.

{
  "name": "add-remove-layers",
  "type": "widget",
  "version": "1.11.0",
  "dependency":  ["jimu-arcgis"],
  "exbVersion": "1.11.0",
  "author": "Jeffrey Thompson",
  "description": "Loads or removes sets of data by groups or individual layers",
  "copyright": "City of Arlington",
  "license": "",
  "properties": {},
  "translatedLocales": [
    "en"
  ],
  "defaultSize": {
    "width": 800,
    "height": 500
  },
  "publishMessages":  ["DATA_SOURCES_CHANGE"]
}

What am I missing? @Yueyang_Li @WeiYing1 @TonghuiMing 

GIS Developer
City of Arlington, Texas
0 Kudos
Yueyang_Li
New Contributor III

@JeffreyThompson2, sorry for the late reply.

The DataSourcesChange is a message action, that must be configured in the widget settings (builder).

If you want an action to add the new layer data source to the map widget in runtime, you can use the DataActionList component like AddData widget. The select widget can use the new layer data source after doing that. The component will calculate the supported data actions based on the added widgets and show a dropdown list.

Yueyang_Li_0-1720687533804.png

 

I'm glad you have found a workaround. But if you want to use the DataActionList and have other issues, you can reply there.

0 Kudos
JeffreyThompson2
MVP Regular Contributor

The DataSourcesChange message did not work, but I got something functional with the JimuMapView.addRemoveDataOnMap() method.

 

 

setTimeout(() => {
				console.log(mapLayer.sourceJSON)
				const data: DataSourceJson = {
					id: 'custom_' + layerGroup.layers[i].id,
					layerId: `${mapLayer.sourceJSON["id"]}`,
					itemId: layerGroup.layers[i].id,
					url: layerGroup.layers[i].url,
					type: 'FEATURE_LAYER',
					geometryType: mapLayer.sourceJSON["geometryType"],
					label: mapLayer.title,
					portalUrl: 'url'
				}
				const dataJson = Immutable(data)
				const dataSourceOptions = {
					id: layerGroup.layers[i].id,
					layer: mapLayer,
					dataSourceJson: dataJson
				}
				
				console.log(dataSourceOptions)
				const dataSource = DataSourceManager.getInstance().createDataSource(dataSourceOptions)
				dataSource.then((source) => {
					
						console.log(source)
						const sourceId = source.id
						const addMapData: AddToMapData = {
							mapWidgetId: 'widget_9',
							messageWidgetId: 'widget_33',
							jimuMapViewId: jimuMapView.id,
							dataSourceId: sourceId,
							type: ActionType.MessageAction,
							title: 'Add Data',
							dataChangeType: DataChangeType.Create,
							dataChangeStatus: DataChangeStatus.Fulfilled
						}
						console.log(addMapData)
						mapDatas[sourceId] = addMapData
						
					
					setTimeout(() => {
						jimuMapView.addOrRemoveDataOnMap(mapDatas)
					}, 50)
				})

}, 3000)

 

GIS Developer
City of Arlington, Texas
0 Kudos