Select to view content in your preferred language

Random datasource errors with Table widget when programatically adding new layers+daatsources to EB map

177
6
3 weeks ago
EmoryHorvath
Emerging Contributor

I'm using a variation of the latest patented Jeffrey Thompson EB 1.16 method of adding new layers+datasources to an EB map widget, from a custom widget.

Link to Jeffrey's code sample:Add/Remove Layers 3.0 - Full Settings Panel Support for Enterprise Deployment 

However the Table widget that i have linked to the map widget is throwing random datasource-not-found errors, for example: "Can not find data source: 19442c5c7d2-layer-5".

These errors happen randomly, with about a quarter of the added layers, and prevent the data table from displaying correctly in the table widget.  It's not the same layer(s) each time which error, but a random subset of layers.  Note that i'm typically adding multiple layers at the same time, depending on which theme the user selects.  That means i'm calling my addLayer() function below multiple times in quick succession.

Has anyone seen this sort of thing before?  I'm using EB 1.16.

I include some code snippets below:

export async function addLayer(mapView, layerList, layerIndex, visible, labels=null) {
    const layer = layerList.layers[layerIndex];
    // Has the layer already been added to the map?
    let mlayer = mapView.view.map.layers.find((l) => { return (l.myIndex != undefined && l.myIndex == layerIndex) });
    if (mlayer == undefined) {           // If not, then add it.
        var newlayer = createLayer(layer, layerIndex, visible, labels);		// A complicated function that creates a new FeatureLayer/GroupLayer/ImageLayer/etc.
        if (newlayer != null) {
           addLayerAndDataSource(mapView, newlayer);
        }
    } else {
        console.log('Layer: \'' + layer.name + '\' is already on map.');
    }
}

function addLayerAndDataSource(jmv, layer, index = -1) {
    if (index == -1) {      // Just append it to end of layer list
        jmv.view.map.add(layer);
    } else {      // Insert it at a specific order in the layer list
        jmv.view.map.add(layer, index);
    }
    if (layer.type === 'feature') {
        reactiveUtils.when(() => layer.loaded, () => { makeLayerView(jmv, layer); })
    } else if (layer.type === 'group') {
        // Need to also make the views & data sources for all the child featurelayers.
        layer.allLayers.forEach((childlayer) => {
            if (childlayer.type === 'feature') {
                reactiveUtils.when(() => childlayer.loaded, () => { makeLayerView(jmv, childlayer); })
            }
        });
    }
}

const makeLayerView = async (jmv, layer) => {
    const dataSource = await createDataSource(layer.id, layer);
    const layerView = await jmv.createJimuLayerView(layer, null, 0, dataSource, true);
}

const createDataSource = async (dsId: string, layer: object): Promise<DataSource> => {
    const dsJson = await fetchDataSourceJson(dsId, layer);
    const dsOptions: FeatureLayerDataSourceConstructorOptions = {
        id: dsId,
        dataSourceJson: dsJson
    }
    return DataSourceManager.getInstance().createDataSource(dsOptions);
}

const fetchDataSourceJson = async (dsId: string, layer: object): Promise<IMDataSourceJson> => {
    const dsJson = await dataSourceJsonCreator.createDataSourceJsonByJSAPILayer(dsId, layer);
    return dsJson;
}

 

 

 

0 Kudos
6 Replies
SerjStol
Frequent Contributor

Does the widget also automatically adds the layers to the Table Widget ?

0 Kudos
EmoryHorvath
Emerging Contributor

The Table widget is configured with the new "Interact with a Map widget" option.  I think this is a new option that just showed in EB 1.16.  Thus the Table widget is apparently automagically notified when new layers/datasources are added to the Map widget.

SerjStol
Frequent Contributor

Oh thats a great feature which I am currently trying to develop in my custom widget! But its ExB 1.14 as we are using Enterprise 11.3 which  does not have this latest Table Widget 😭

0 Kudos
JeffreyThompson2
MVP Regular Contributor

I suspect your issue is in line 6 where you call createLayer(). You do not have an await operator on that line so it sometimes proceeds to the next function before the createLayer() function is complete. Try adding the await operator to that line then rewriting the createLayer() function to return a Promise that returns newLayer.  

 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

GIS Developer
City of Arlington, Texas
EmoryHorvath
Emerging Contributor

Thanks, i'll give it a try.  I don't immediately see anything in my createLayer() function that should need an await, but one never knows.  The error does sort of feel like a timing/asynchronous-related sort of thing, doesn't it?  However i'm using brand-new EB 1.16 functionality, which makes me fear maybe a bug in ESRI's code too.

0 Kudos
JeffreyThompson2
MVP Regular Contributor

Keep in mind that by default JavaScript does not wait for one function to complete before calling the next function, so if createLayer() is a complex process, it may not be finished before addLayerAndDatasource() starts.

These issues can be very hard to diagnosis because your console will also lie to you, showing you what the result of the function is and not necessarily what data is available at the moment the next function is called.

GIS Developer
City of Arlington, Texas
0 Kudos