2

I am working on an application that will retrieve data from various sources and construct ESRI GraphicsLayer objects from the data and display it on a map. I have created custom FeatureLayers before but this project requires the use of GraphicsLayers because I need to be able to toggle the visibility of layers. The code below fetches the data from the host and puts it into a GraphicsLayer.

define(["dojo/_base/declare", "dojo/_base/array", "dojo/request", "esri/graphic", "esri/geometry/Geometry", "esri/InfoTemplate"],

  function (declare, array, request, Graphic, Geometry, InfoTemplate) {
    return declare(null, {
      getAllCurrentReadings: function () {
        var rtn = [];
        var stations = ["S", "SN", "AN", "UP", "GR", "PL", "SR", "J", "N", "FL"];
        array.forEach(stations, function (item, i) {
          request.post("includes/buoybay_proxy.php", {
            data: {
              "method": "RetrieveCurrentReadings",
              "params": "CBIBS," + item + ",113f8b...f27e0a0bb" // NOTE: id: 1 is necessary as well but is added manually by jsonRPCClient
            },
            sync: true,
            handleAs: "json"
          })
            .then(
              function (response) {
                var gfx, attr, t;
                //console.log(response);
                // Now build the Graphic Object and push it into rtn
                gfx = new Graphic();
                gfx.spatialReference = {
                  wkid: 102100
                };

                // Define attribute object
                attr = {};
                attr["station"] = response.station;
                attr["title"] = translateStationID(response.station);
                for (var j = 0; j < response.measurement.length; j++) {
                  attr[String(response.measurement[j])] = response.value[j];
                }
                gfx.attributes = attr;

                // Define geometry object
                gfx.geometry = new Geometry(gfx.spatialReference, "point");
                gfx.geometry.spatialReference = {
                  wkid: 102100
                };
                gfx.geometry.type = "point";
                t = esri.geometry.geographicToWebMercator(new esri.geometry.Point(attr["longitude"], attr["latitude"], gfx.spatialReference));
                gfx.geometry.x = t.x;
                gfx.geometry.y = t.y;

                // Define infoTemplate object
                gfx.infoTemplate = new esri.InfoTemplate();
                gfx.infoTemplate.setTitle(attr["title"]);
                gfx.infoTemplate.setContent("${*}");

                // Define symbol
                gfx.symbol = new esri.symbol.PictureMarkerSymbol("../images/marker.png", 15, 15);

                //console.log(gfx);
                rtn.push(gfx);
              },
              function (error) {
                console.log("Error: " + error + "\n");
              }
          )
        });
        //console.log(rtn);
        return rtn;
      }
    });
  }
);

This code seems to construct the GraphicsLayers properly but when I add them to the map object no points are displayed on the map. The code I use to add them to the map object is below.

require(["dojo/parser", "dojo/_base/array", "dijit/layout/BorderContainer", "dijit/layout/ContentPane", "dojo/ready", "esri/map", "esri/layers/ArcGISTiledMapServiceLayer", "js/cbibsGfxModule", "dojo/domReady!"],
    function(parser, array, BorderContainer, ContentPane, ready, map, ArcGISTiledMapServiceLayer, cbibsGfxModule) {
        var Map, cbibs, gfxLayer, t = [];
        function init() {
            Map = new map("mapDiv", {
              basemap: "oceans",
              center: [-77.0357, 38.7877],
              zoom: 7
            });
            dojo.connect(Map, "onLoad", displayData); // Map didn't load until 3rd arg was a function name; why?

            function displayData() {
                cbibs = new cbibsGfxModule();
                t = cbibs.getAllCurrentReadings();
                gfxLayer = new esri.layers.GraphicsLayer();
                array.forEach(t, function (item) {
                    gfxLayer.add(item);
                    Map.graphics.add(item);
                });
                gfxLayer.spatialReference = {
                    wkid: 102100
                };
                //Map.addLayer(gfxLayer); // Add GraphicsLayer to Map object
                console.log(Map); // Custom GraphicLayers are under _layers
            };
        };
        dojo.ready(init);
    }
);

I realize that gfxLayer.add(item) and Map.graphics.add(item) are somewhat redundant but even with the data in two locations in the Map object the points are still not displayed on the map.

I've been working on this for some time now and I really am fresh out of ideas. Any help anyone could offer would be greatly appreciated. Thank you.

  • "this project requires the use of GraphicsLayers because I need to be able to toggle the visibility of layers" – both feature layers and graphics layers have show() and hide() methods that you can use to toggle visibility. You're mixing AMD and legacy global references throughout your code which doesn't make things any easier. Please break this down in to a simpler case. For instance, can you retrieve data from your server and put it on a map without creating a module? – Derek Swingley Oct 14 '13 at 21:31
  • I've updated my answer with a bit of code that you might use. – raykendo Nov 1 '13 at 5:09
3

Besides the comments Derek has made, there are a few noticeable issues with the construction code.

  1. When you set your geometry spatialReference, you need to use the esri.SpatialReference constructor with the wkid object as a parameter. I've had graphics not show up because I set the spatialReference = {wkid: 102100}.
  2. Use graphic.setSymbol(), graphic.setAttributes(), graphic.setGeometry(), and graphic.setInfoTemplate() to set those parameters, if you're not using them in the constructor.
  3. When you're running esri.geometry.geographicToWebMercator(), and you're passing in a new esri.geometry.Point, you don't need to add a spatialReference if you're passing in longitude and latitude. Without a spatialReference, the point assumes it's in geographic {wkid: 4326}; I'm really surprised the code didn't break when you ran it using a broken Web Mercator spatial reference (see 1);
  4. Finally, you're using an asynchronous server call using request.post, then you fill the array with graphics when the browser receives the results. The problem is, you've already returned that empty array to populate the map before it could be filled. You should probably look into dojo.deferred to handle the asynchronous results.

Try this and see if it helps:

define(["dojo/_base/declare", "dojo/_base/array", "dojo/request", "dojo/DeferredList", "esri/graphic", "esri/geometry/webMercatorUtils", "esri/geometry/Point", "esri/InfoTemplate", "esri/symbols/PictureMarkerSymbol"],

  function (declare, array, request, DeferredList, Graphic, WebMercatorUtils, Point, InfoTemplate, PictureMarkerSymbol) {
    return declare(null, {
      getAllCurrentReadings: function () {
        var defList = [];
        var stations = ["S", "SN", "AN", "UP", "GR", "PL", "SR", "J", "N", "FL"];
        array.forEach(stations, function (item, i) {
          // get deferred object returned from the post.
          var requestDef = request.post("includes/buoybay_proxy.php", {
            data: {
              "method": "RetrieveCurrentReadings",
              "params": "CBIBS," + item + ",113f8b...f27e0a0bb" // NOTE: id: 1 is necessary as well but is added manually by jsonRPCClient
            },
            sync: true,
            handleAs: "json"
          }).then(
              function (response) {
                var gfx, attr, geom, symbol, info;
                //console.log(response);

                // Define attribute object
                attr = {};
                attr["station"] = response.station;
                attr["title"] = translateStationID(response.station);
                for (var j = 0; j < response.measurement.length; j++) {
                  attr[String(response.measurement[j])] = response.value[j];
                }

                // Define geometry object
                geom = WebMercatorUtils.geographicToWebMercator(new Point(attr["longitude"], attr["latitude"]));

                // Define infoTemplate object
                info = new InfoTemplate({
                    title: attr["title"],
                    content: "${*}"
                });

                // Define symbol
                symbol = new PictureMarkerSymbol("../images/marker.png", 15, 15);

                // Now build the Graphic Object and push it into results list;
                gfx = new Graphic(geom, symbol, attr, info);

                //console.log(gfx);
                return gfx;
              },
              function (error) {
                console.log("Error: " + error + "\n");
              }
          );

          defList.push(requestDef);

        });

        //console.log(rtn);
        return new DeferredList(defList);
      }
    });
  }
);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.