legend event "finished"

974
5
05-22-2018 01:07 PM
BlairJones
New Contributor III

ArcGIS API 4.6;  I want to create user interface elements within a legend.  There seems to be no ESRI methods for this, so I am trying to capture the document elements created by the legend widget.  I want a static legend.

First I create a number of FeatureLayer with empty source features array.   I add these to a map and create the legend.  Next, I want to copy the innerHTML of the document element containing legend and finally destroy the legend and remove all FeatureLayer.  From the copy I can construct my version of legend.

My problem is event timing.  Is there a deterministic method to signal complete construction of new esriLegend in the DOM?  I have tried watchUtil.when(legend,"container") property, but I cant find a method to use with dojo/aspect.after.

What works is to invoke esriLegend then use setTimeout(), set for a few hundred miliseconds, at which point I can copy the completed DOM element and destroy the legend.

Please suggest a better way!

Thanks, Blair

//  makeLegend.js    May 22, 2018    abj3
if (!window.VaFWIS) { window.VaFWIS = {}; }
if (!VaFWIS.lib) { VaFWIS.lib = {}; }

require([
    "esri/layers/FeatureLayer",
    "esri/widgets/Legend"
], function (FeatureLayer, esriLegend) {

        VaFWIS.lib.makeLegend = function () {

// esri/widgets/legend creates a dynamic symbol legend connected to map featureLayers
// VaFWIS.lib.makeLegend - make an esriLegend and copy DOM element as a static legend
//  1) map.add featureLayers created from VaFWIS.layerDef having layerInfo
//  2) define legend info
//  3) invoke esri/widgets/legend which dynamically inserts HTML into "theLegend"
//  4) save  "theLegendContainer" innerHTML
//  5) destroy legend
//  6) map.remove featureLayers
//  7) restore saved "theLegendContainer" innerHTML
//  😎 (future) add legend item specific ui controls
//      a) re-order layers by dragging
//      b) change opacity

            var legendLayerInfos = [];
            var keys = Object.keys(VaFWIS.layerDef);
            for (var k = 0; k < keys.length; k++) {
                var layerDef = VaFWIS.layerDef[keys];
                if (layerDef.layerInfo) {
                    if (VaFWIS.debug == true) {
                        console.log("makeLegend for " + layerDef.id);
                    }
                    var featureLayer = FeatureLayer(
                        {
                            "fields": layerDef.layerInfo.fields
                            , "geometryType": layerDef.layerInfo.geometryType
                            , "id": "theLegend_" + layerDef.id
                            , "objectIdField": layerDef.layerInfo.objectIdField
                            , "popupTemplate": layerDef.layerInfo.popupTemplate
                            , "renderer": layerDef.layerInfo.renderer
                            , "spatialReference": layerDef.layerInfo.spatialReference
                            , "source": []
                            , "visible": true
                        }
                    );
                    VaFWIS.map.add(featureLayer);
                    legendLayerInfos.push(
                        {
                            "layer": featureLayer
                            , title: layerDef.title
                        });
                }
            }
            // construct legend; after scheduleRenderer then save HTML and destroy legend
            legend = new esriLegend(
                {
                    view: VaFWIS.mapView,
                    container: "theLegend",
                    layerInfos: legendLayerInfos
                }
            );
            setTimeout(function (legend) {
                var containerContent = $("#theLegendContainer").html();
                legend.destroy();
                VaFWIS.map.removeMany(VaFWIS.map.layers.filter(
                    function (lyr) {
                        return lyr.id.indexOf("theLegend_") == 0;
                    }
                ));
                $("#theLegendContainer").html(containerContent);
                $("#theLegendContainer").css("visibility", "visible");
            }.bind(null, legend), 250);
        }
    });

0 Kudos
5 Replies
RobertScheitlin__GISP
MVP Emeritus

Blair,

   See if this works for you:

watchUtils.whenOnce(legend, "container", function(evt){
  console.info(legend.container);
});
0 Kudos
BlairJones
New Contributor III

Thanks Robert,

I inserted your (modified) code after legend = new esriLegend(...

watchUtils.whenOnce(legend, "container", function(evt){
  console.log(legend.container.innerHTML);
});

innerHTML is "No legend"

Then after setTimeout for 250ms, the legend is complete.

Good health!
Blair
0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Blair,

   So I thought that you just needed to make sure the legend widget was created. Sounds like you want to know when it is done rendering the layers in the map. Is that correct?

0 Kudos
BlairJones
New Contributor III

Thanks Robert,

Yes, I want the complete rendered legend.

Good health!

Blair

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Blair,

  I can not find anything to listen to for when the legend is done rendering.

0 Kudos