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.
@Wei_Ying 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?
Solved! Go to Solution.
Hi @YueyangLi @QunSun @JeffreyThompson2 @Wei_Ying
In the scenario related to DataSource, is there an effective way to switch WebMaps with a DataSource reference at runtime?
Currently, I am changing the WebMap using the following code:
jimuMapView.view.map = newWebMap;
However, with this approach, I am unable to access DataActions such as "Export" and "Add to Table." I have more than 5 WebMaps, and based on certain conditions, I need to switch between them with the DataSource reference. Could you suggest any ideas on how to achieve this?
Hi Jeffrey, I am working on a custom widget and I want to be able to create an output data source that is compatible with Map Widget. I have successfully created an output data source. When navigating to the settings panel for Table and Chart widgets, I am able to see my output data source and select it. But when selecting Map Widget -> Select Map -> Select data I do not see the output data source in this menu.
Do you have any thoughts on how to get the output data source to show up in the Map Widget?
Hi @JustinWade , the map widget can only uses map data source, I assume your output data source is a feature layer.
To add the layer data source to map widget, you can use the DataActionList component to add it to the map in the runtime (need the end users to click the 'Add to map' button, please see add data widget).
If you want to add the layer automatically as soon as it is created. Try the message actions. Add '"publishMessages": ["DATA_SOURCES_CHANGE"]' to your widget's manifest.json and publish the message when your layer data source is created. Please note, the builder users need to configure the message action before publishing the app.
const dataSourcesChangeMessage = new DataSourcesChangeMessage(widgetId, DataSourcesChangeType.Create, dataSources)
MessageManager.getInstance().publishMessage(dataSourcesChangeMessage)
Thanks @YueyangLi , publishing a message worked for me leveraging message actions. Layer added to map and layer list, panned and zoomed after actions were configured. However, my hosted feature layer has multiple layers within it, but my code only adds the first layer. I see in Add Data widget I can add the whole hosted feature layer and multiple layers are grouped together. Do I just need to iterate through all layers and create multiple FeatureLayer objects via the url rather than itemid, and how do i group them like Add Data Widget? I am currently adding a Feature Layer using portal item ID, fetching data source JSON and then creating a data source and publishing a message.
// Function to create the DataSource JSON
const fetchDataSourceJson = async (dsId: string, layer: FeatureLayer): Promise<IMDataSourceJson> => {
try {
const dsJson = await dataSourceJsonCreator.createDataSourceJsonByJSAPILayer(dsId, layer);
console.log('DataSource JSON:', dsJson);
return dsJson;
} catch (error) {
throw new Error(`Failed to fetch DataSource JSON: ${error}`);
}
}
// Function to create the DataSource
const createDataSource = async (dsId: string, layer: FeatureLayer): Promise<DataSource> => {
try {
const dsJson = await fetchDataSourceJson(dsId, layer);
const dsOptions: FeatureLayerDataSourceConstructorOptions = {
id: dsId,
dataSourceJson: dsJson
}
console.log('DataSource Constructor Options:', dsOptions);
const dataSource = await DataSourceManager.getInstance().createDataSource(dsOptions);
// Ensure the data source is fully initialized
if (dataSource.isDataSourceSet && !dataSource.areChildDataSourcesCreated()) {
await dataSource.childDataSourcesReady();
}
return dataSource;
} catch (error) {
throw new Error(`Failed to create DataSource: ${error}`);
}
}
// Main function to create the DataSource by Layer and publish the message
export async function createDataSourceByLayer(
itemId: string,
widgetId: string
): Promise<DataSource> {
try {
const layer = new FeatureLayer({
portalItem: {
id: itemId
},
id: `incidentFl_${itemId}`
});
// Wait for the layer to load to ensure all properties are available
await layer.load();
// Construct the DataSource ID
const dsid = `incidentDs_${layer.id}`;
// Create the DataSource
const dataSource = await createDataSource(dsid, layer);
// Publish message
const dataSourcesChangeMessage = new DataSourcesChangeMessage(
widgetId,
DataSourcesChangeType.Create,
[dataSource]
);
MessageManager.getInstance().publishMessage(dataSourcesChangeMessage);
return dataSource;
} catch (error) {
console.error(`Error in createDataSourceByLayer: ${error}`);
throw error;
}
}
@SerjStol, if your layers are from the same feature service/map service, you can create a feature service/map service data source and then add it to the map, like what the Add data widget is doing.
If your layers are from multiple service, you can create a group layer item and then create a group layer data source based on it.
To create group layer/map service/feature service data source, you need to 1. change the type of the data source json 2. add the url (the service url), the portalUrl and itemId if you have, and 3. remove the Maps SDK layer (the data source will create one when needed).
{
id: 'ds1',
sourceLabel: 'the data source name',
type: DataSourceTypes.FeatureService, // MapService, or GroupLayer,
url: 'https://xxx/FeatureServer', // group layer should not have the url
itemId: 'xxx',
portalUrl: 'https://xxx.arcgis.com'
}
@YueyangLi my hosted feature layer in Portal contains multiple layers within. When I create FeatureLayer using portal itemid as per code above or url, it creates a feature layer and then i use createDataSourceJsonByJSAPILayer from that layer but looking at the logs it only creates data source only for the first layer 0, so only single layer data source is created. Maybe i am not using the correct method to create DataSourceJson?
@YueyangLi Ok i've managed to get it to work! Looking through some code in Analysis widget i found this way of creating DataSourceJson from feature service URL works correctly and adds all layers as a group to list widget and the map. I am adding them via publishing of the message like Add Data widget.
const dsJson: DataSourceJson = dataSourceJsonCreator.createDataSourceJsonByLayerDefinition(dsId, serviceDefinition, url)?.asMutable({ deep: true })