Is it the case that GraphicsLayer doesn't fire OnUpdateEnd?

2322
2
05-11-2012 04:40 AM
StephenLead
Regular Contributor III
As far as I can see, a GraphicsLayer doesn't fire the Map's onUpdateEnd event.

1) is that correct?
2) why doesn't it fire onUpdateEnd, given that it's a subclass of Layer, which does fire the onUpdateEnd event?

To illustrate, run the attached code. The map and dynamic layer both fire the onUpdateEnd event, but the graphicsLayer doesn't.

A workaround will be to create a featureLayer from a featureCollection based on the graphicsLayer - but why is this necessary?

Thanks,
Steve

EDIT: it also appears that the map's onUpdateEnd will fire before the graphicsLayer has finished drawing? Try the code below, which is zoomed to the full extent of the USA. The map's onUpdateEnd event fires, then the graphics draw a few seconds later.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=7,IE=9" />
    <!--The viewport meta tag is used to improve the presentation and behavior of the samples 
      on iOS devices-->
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
    <title>Create Map</title>
    <link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/2.8/js/dojo/dijit/themes/claro/claro.css">
    <script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=2.8"></script>
    <script type="text/javascript">
      dojo.require("esri.map");
      dojo.require("esri.tasks.query");
      var map;
      var graphicsLayer = new esri.layers.GraphicsLayer();


      function init() {
        //var startExtent = new esri.geometry.Extent(-83.41, 31.98, -78.47, 35.28, new esri.SpatialReference({wkid:4326}));
        map = new esri.Map("map")//,{extent:esri.geometry.geographicToWebMercator(startExtent)});
                
        var basemap = new esri.layers.ArcGISTiledMapServiceLayer("http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer");
        map.addLayer(basemap);
        
        var dynamicLayer = new esri.layers.ArcGISDynamicMapServiceLayer("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Population_World/MapServer");
        map.addLayer(dynamicLayer);


        var queryTask = new esri.tasks.QueryTask("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer/3");
        
        //build query filter
        var query = new esri.tasks.Query();
        query.returnGeometry = true;
        query.outFields = ["*"];
        query.outSpatialReference = {"wkid":102100};
        query.where = "1=1";
        
        queryTask.execute(query, addPointsToMap);
        
        dojo.connect(map, "onLoad", function () {
         dojo.connect(map, "onUpdateEnd", function() {
          console.log("map update end");
         });
         dojo.connect(graphicsLayer, "onUpdateEnd", function() {
          console.log("graphicsLayer update end");
         });
         dojo.connect(dynamicLayer, "onUpdateEnd", function() {
          console.log("dynamic layer update end");
         });
     });
      }
      
      function addPointsToMap(featureSet) {
       var symbol = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color([255,255,255,0.35]), 1),new dojo.Color([125,125,125,0.35]));
       
       for (var i=0, il=featureSet.features.length; i<il; i++) {
        var graphic = featureSet.features;
        graphic.setSymbol(symbol);
        graphicsLayer.add(graphic);
       }
       map.addLayer(graphicsLayer);
      
      }


      dojo.addOnLoad(init);
    </script>
  </head>
  <body class="claro"></body>
</html>
0 Kudos
2 Replies
derekswingley1
Frequent Contributor
Hi Steve,

I know you've posted a simplified example here, but why not use a feature layer? It's less code, and you get the events you want.

To your point of onUpdateEnd being implemented at the esri.Layer class. While true, the description says:
Fires when a layer has finished updating its content. It is the responsibility of the subclass to determine when this event is fired.


So it's up to subclasses of Layer to implement onUpdateEnd. As you've found out, the graphics layer doesn't implement onUpateEnd. Again, I would say use a feature layer.

What are you trying to do?
0 Kudos
StephenLead
Regular Contributor III
Thanks Derek.

the graphics layer doesn't implement onUpateEnd


Can you please submit two enhancement requests:

1. a graphicsLayer should handle onUpdateStart and onUpdateEnd events
2. a graphicsLayer should interact with the Map's onUpdateStart and onUpdateEnd events

The current behaviour seems like an oversight, since the map is aware of the layer's existence (map.graphicsLayerIds lists the graphicsLayer) but not its drawing status. If the graphics are still drawing, then really the map hasn't finished updating.

So it's up to subclasses of Layer to implement onUpdateEnd.


Is this responsibility Esri's (as authors of the JS API), or can we as 3rd party developers do anything about it?

why not use a feature layer? It's less code, and you get the events you want. What are you trying to do?


I'm running an unknown number of deferred queries, and I want to draw the results. I'll see whether I can draw them as a featureLayer based on a featureCollection, rather than a graphicsLayer.

Cheers,
Steve
0 Kudos