On Click -> Layer event works with Hosted Feature Service, but not a AGS MapService?

1385
6
Jump to solution
01-06-2017 05:29 PM
AdamCrateau
New Contributor III

This code works with a hosted feature service:

// Define hook for Parcel Layer
var parcelLayer = map.getLayer(this._parcelLayerID);

// Define the Selected Parcels Symbol
var highlightSymbol = this._getHighlightSymbol();

// Define OnClick event for clicking on a Parcel
this.onParcelClick = on.pausable(parcelLayer, 'click', lang.hitch(function (e) {
 var taxlotString = esriLang.substitute(e.graphic.attributes, "${TAXLOT}");
 var ownerString = esriLang.substitute(e.graphic.attributes, "${OWNERNAME}");
 if (ownerString.length > 24) ownerString = ownerString.substring(0, 24) + "...";
 var attr = { "Taxlot": taxlotString };
 var highlightGraphic = new Graphic(e.graphic.geometry, highlightSymbol, attr);
 map.graphics.add(highlightGraphic);
}));‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

However when I use a map service hosted on our own AGS, it does not.  I can get a reference to the parcel layer using LayerInfos, but when I click on the map...nothing.   Any ideas?

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Adam,

   That now makes sense. Your code is flawed when it come to layers coming from a map service vs. hosted one.

Here is what should work:

_getLayerID: function _getLayerID(map, layerTitle) {
  //local function to fetch the LayerID of layer in the map
  var layerID;
  if (this.map.itemId) {
    LayerInfos.getInstance(this.map, this.map.itemInfo)
      .then(lang.hitch(this, function(operLayerInfos) {
        operLayerInfos.traversal(function(layerInfo) {
          if (layerInfo.title == layerTitle){ 
            layerID = layerInfo.id;
          }
        });
      }));
  } else {
    var itemInfo = this._obtainMapLayers();
    LayerInfos.getInstance(this.map, itemInfo)
      .then(lang.hitch(this, function(operLayerInfos) {
        operLayerInfos.traversal(function(layerInfo) {
          if (layerInfo.title == layerTitle){ 
            layerID = layerInfo.id;
          }
        });
      }));
  }
  return layerID;
},
      _obtainMapLayers: function() {
        // summary:
        //    obtain basemap layers and operational layers if the map is not webmap.
        var basemapLayers = [],
          operLayers = [];
        // emulate a webmapItemInfo.
        var retObj = {
          itemData: {
            baseMap: {
              baseMapLayers: []
            },
            operationalLayers: []
          }
        };
        array.forEach(this.map.graphicsLayerIds, function(layerId) {
          var layer = this.map.getLayer(layerId);
          if (layer.isOperationalLayer) {
            operLayers.push({
              layerObject: layer,
              title: layer.label || layer.title || layer.name || layer.id || " ",
              id: layer.id || " "
            });
          }
        }, this);
        array.forEach(this.map.layerIds, function(layerId) {
          var layer = this.map.getLayer(layerId);
          if (layer.isOperationalLayer) {
            operLayers.push({
              layerObject: layer,
              title: layer.label || layer.title || layer.name || layer.id || " ",
              id: layer.id || " "
            });
          } else {
            basemapLayers.push({
              layerObject: layer,
              id: layer.id || " "
            });
          }
        }, this);

        retObj.itemData.baseMap.baseMapLayers = basemapLayers;
        retObj.itemData.operationalLayers = operLayers;
        return retObj;
      },‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

View solution in original post

0 Kudos
6 Replies
RobertScheitlin__GISP
MVP Emeritus

Are there any errors in the browser console?

0 Kudos
AdamCrateau
New Contributor III

No errors or other message in the console.  On opening, my widget temporarily turns off the infoWindow on the parcel layer and changes the cursor to a crosshair.  When I click nothing happens, whereas before it would add the clicked-on parcel to map.graphics as expected.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

That is just completely strange that you are not given some error when you click on the map? Do you have an error handler as well as a result handler for your deferred task like queryTask or FeatureLayer.selectFeatures?

0 Kudos
AdamCrateau
New Contributor III

Robert, Just to follow up after more testing:   Here's the code I'm currently using:

_getLayerID: function _getLayerID(map, layerTitle) {
  //local function to fetch the LayerID of layer in the map
  var layerID;
  LayerInfos.getInstance(map, map.itemInfo).then(lang.hitch(function (operLayerInfos) {
    operLayerInfos.traversal(function(layerInfo) {
      if (layerInfo.title == layerTitle){ 
        layerID = layerInfo.id;
      }
    });
  }));
 return layerID;
},‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

startup: function startup() {
  var _this = this; // used to fix the scope of objects inside events
  var map = this.map;
  var parcelLayerName = this.config.ParcelLayer_Name; //Name of parcel layer in the map, set from config.json
  
  var parcelLayer = map.getLayer(this._getLayerID(map, parcelLayerName));

  // Define the Selected Parcels Symbol
  var highlightSymbol = this._getHighlightSymbol();

  ////////////// Listener Events
  // Define OnClick event for clicking on a Parcel
  this.onParcelClick = on.pausable(parcelLayer, 'click', lang.hitch(function (e) {
    var taxlotString = esriLang.substitute(e.graphic.attributes, "${TAXLOT}");
    var ownerString = esriLang.substitute(e.graphic.attributes, "${OWNERNAME}");
    if (ownerString.length > 24) ownerString = ownerString.substring(0, 24) + "...";

    var attr = { "Taxlot": taxlotString };
    var highlightGraphic = new Graphic(e.graphic.geometry, highlightSymbol, attr);

    map.graphics.add(highlightGraphic);‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

    ...
  };
  ...

The rest end point for the map service layer I'm working with is https://....arcgis/rest/services/Public/PlanningBaseData/MapServer/2  

The layerID returned from my _getLayerID function is "PlanningBaseData_5029_2".  

The error I'm getting now is:

TypeError: Cannot read property 'on' of undefined

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Adam,

   That now makes sense. Your code is flawed when it come to layers coming from a map service vs. hosted one.

Here is what should work:

_getLayerID: function _getLayerID(map, layerTitle) {
  //local function to fetch the LayerID of layer in the map
  var layerID;
  if (this.map.itemId) {
    LayerInfos.getInstance(this.map, this.map.itemInfo)
      .then(lang.hitch(this, function(operLayerInfos) {
        operLayerInfos.traversal(function(layerInfo) {
          if (layerInfo.title == layerTitle){ 
            layerID = layerInfo.id;
          }
        });
      }));
  } else {
    var itemInfo = this._obtainMapLayers();
    LayerInfos.getInstance(this.map, itemInfo)
      .then(lang.hitch(this, function(operLayerInfos) {
        operLayerInfos.traversal(function(layerInfo) {
          if (layerInfo.title == layerTitle){ 
            layerID = layerInfo.id;
          }
        });
      }));
  }
  return layerID;
},
      _obtainMapLayers: function() {
        // summary:
        //    obtain basemap layers and operational layers if the map is not webmap.
        var basemapLayers = [],
          operLayers = [];
        // emulate a webmapItemInfo.
        var retObj = {
          itemData: {
            baseMap: {
              baseMapLayers: []
            },
            operationalLayers: []
          }
        };
        array.forEach(this.map.graphicsLayerIds, function(layerId) {
          var layer = this.map.getLayer(layerId);
          if (layer.isOperationalLayer) {
            operLayers.push({
              layerObject: layer,
              title: layer.label || layer.title || layer.name || layer.id || " ",
              id: layer.id || " "
            });
          }
        }, this);
        array.forEach(this.map.layerIds, function(layerId) {
          var layer = this.map.getLayer(layerId);
          if (layer.isOperationalLayer) {
            operLayers.push({
              layerObject: layer,
              title: layer.label || layer.title || layer.name || layer.id || " ",
              id: layer.id || " "
            });
          } else {
            basemapLayers.push({
              layerObject: layer,
              id: layer.id || " "
            });
          }
        }, this);

        retObj.itemData.baseMap.baseMapLayers = basemapLayers;
        retObj.itemData.operationalLayers = operLayers;
        return retObj;
      },‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
AdamCrateau
New Contributor III

Awesome.  Thank you Robert!

0 Kudos