Select to view content in your preferred language

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

1585
6
Jump to solution
01-06-2017 05:29 PM
AdamCrateau
Occasional Contributor

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
Occasional Contributor

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
Occasional Contributor

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
Occasional Contributor

Awesome.  Thank you Robert!

0 Kudos