onClick select features from multiple layers/popup issue

6853
8
Jump to solution
03-05-2015 06:13 AM
RyanSellman
Occasional Contributor II

Hello,

I am trying to set up an app that gives the user the ability to choose which layers they want to identify.  I have multiple feature layers added to the map each in selection mode and each has an assigned infoTemplate.  I have an onClick event that fires all selections.  I want the results of the multiple queries to be shown in a popup.  The queries all execute just fine, but popups are showing for only one of the layers being selected.  Here is a a quick example of the code I am trying to implement:

var soiltemplate = new PopupTemplate({
          title: "Soil"
        });
   
  var soils = "http://summitmaps.summitoh.net/arcgis/rest/services/Environmental_Mercator/MapServer/2";
         soilsFeatureLayer = new esri.layers.FeatureLayer(soils, {
             mode: esri.layers.FeatureLayer.MODE_SELECTION,
             visible: true,
             outFields: ["*"],
  infoTemplate: soiltemplate
         });
         var symbol = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_NULL, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new dojo.Color([100, 100, 100]), 2), new dojo.Color([0, 0, 255, 0.20]));
         soilsFeatureLayer.setSelectionSymbol(symbol);
         
  var canopytemplate = new InfoTemplate({
          title: "Canopy"
        });

  var canopy = "http://summitmaps.summitoh.net/arcgis/rest/services/Environmental_Mercator/MapServer/5";
         canopyFeatureLayer = new esri.layers.FeatureLayer(canopy, {
             mode: esri.layers.FeatureLayer.MODE_SELECTION,
             visible: true,
             outFields: ["*"],
  infoTemplate: canopytemplate
         });
         var symbol = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_NULL, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new dojo.Color([100, 100, 100]), 2), new dojo.Color([0, 0, 255, 0.20]));
         canopyFeatureLayer.setSelectionSymbol(symbol);

var clickEvent = connect.connect(map, "onClick", selectFeatures);

  function selectFeatures(evt){

  function pointToExtent (map, point, toleranceInPixel) {
   var pixelWidth = map.extent.getWidth() / map.width;
   var toleranceInMapCoords = toleranceInPixel * pixelWidth;
   return new Extent(point.x - toleranceInMapCoords,
  point.y - toleranceInMapCoords,
  point.x + toleranceInMapCoords,
  point.y + toleranceInMapCoords,
  map.spatialReference);
  }



  var query = new esri.tasks.Query();
  query.geometry = pointToExtent(map, evt.mapPoint, 2);



  var deferredCanopy = canopyFeatureLayer.selectFeatures(query, esri.layers.FeatureLayer.SELECTION_NEW); 
  map.infoWindow.setFeatures([deferredCanopy ]);
  map.infoWindow.show(evt.mapPoint);


  var deferredSoil = soilsFeatureLayer.selectFeatures(query, esri.layers.FeatureLayer.SELECTION_NEW); 
  map.infoWindow.setFeatures([deferredSoil]);
  map.infoWindow.show(evt.mapPoint);
   
  }

Using the above snippet of code, the popup for the soilsFeatureLayer is shown, not the canopyFeatureLayer.  I have to be missing something stupid, or maybe this is a bad approach all together?

Thanks for any help in advance!

Tags (2)
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Ryan,

  Here is a sample that demos how to do that with your data (Coding style change to AMD)

<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <!--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>Popup</title>

  <link rel="stylesheet" href="http://js.arcgis.com/3.12/dijit/themes/claro/claro.css">
  <link rel="stylesheet" href="http://js.arcgis.com/3.12/esri/css/esri.css">
  <style>
    html,
    body,
    #map {
      padding: 0;
      margin: 0;
      height: 100%;
    }
  </style>

  <script src="http://js.arcgis.com/3.12/"></script>
  <script>
    var map;
    require([
        "esri/map",
        "esri/dijit/Popup", "esri/dijit/PopupTemplate",
        "esri/layers/FeatureLayer", "esri/symbols/SimpleLineSymbol",
        "esri/symbols/SimpleFillSymbol", "esri/Color",
        "dojo/dom-class", "dojo/dom-construct", "dojo/on",
        "esri/tasks/query", "esri/geometry/Extent",
        "dojo/domReady!"
      ], function (
      Map,
      Popup, PopupTemplate,
      FeatureLayer, SimpleLineSymbol,
      SimpleFillSymbol, Color,
      domClass, domConstruct, on, Query, Extent
    ) {

      var popup = new Popup({}, domConstruct.create("div"));


      map = new Map("map", {
        basemap: "gray",
        zoom: 4,
        infoWindow: popup,
        extent: new Extent({xmin:-9093667.253259916,ymin:4998534.567771332,xmax:-9059993.366364839,ymax:5064387.406860692,spatialReference:{wkid:54032}})
      });

      var soiltemplate = new PopupTemplate({
        title: "Soil"
      });

      var soils = "http://summitmaps.summitoh.net/arcgis/rest/services/Environmental_Mercator/MapServer/2";
      soilsFeatureLayer = new FeatureLayer(soils, {
        mode: FeatureLayer.MODE_SELECTION,
        visible: true,
        outFields: ["*"],
        infoTemplate: soiltemplate
      });
      var symbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_NULL, new SimpleLineSymbol(SimpleFillSymbol.STYLE_SOLID, new Color([100, 100, 100]), 2), new Color([0, 0, 255, 0.20]));
      soilsFeatureLayer.setSelectionSymbol(symbol);

      var canopytemplate = new PopupTemplate({
        title: "Canopy"
      });

      var canopy = "http://summitmaps.summitoh.net/arcgis/rest/services/Environmental_Mercator/MapServer/5";
      canopyFeatureLayer = new FeatureLayer(canopy, {
        mode: FeatureLayer.MODE_SELECTION,
        visible: true,
        outFields: ["*"],
        infoTemplate: canopytemplate
      });
      var symbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_NULL, new SimpleLineSymbol(SimpleFillSymbol.STYLE_SOLID, new Color([100, 100, 100]), 2), new Color([0, 0, 255, 0.20]));
      canopyFeatureLayer.setSelectionSymbol(symbol);

      //var clickEvent = connect.connect(map, "onClick", selectFeatures);
      map.on('click', selectFeatures);

      function pointToExtent(map, point, toleranceInPixel) {
        var pixelWidth = map.extent.getWidth() / map.width;
        var toleranceInMapCoords = toleranceInPixel * pixelWidth;
        return new Extent(point.x - toleranceInMapCoords,
          point.y - toleranceInMapCoords,
          point.x + toleranceInMapCoords,
          point.y + toleranceInMapCoords,
          map.spatialReference);
      }

      function selectFeatures(evt) {
        var query = new Query();
        query.geometry = pointToExtent(map, evt.mapPoint, 2);
        var deferredCanopy = canopyFeatureLayer.selectFeatures(query, FeatureLayer.SELECTION_NEW);
        var deferredSoil = soilsFeatureLayer.selectFeatures(query, FeatureLayer.SELECTION_NEW);
        map.infoWindow.setFeatures([deferredSoil, deferredCanopy]);
        map.infoWindow.show(evt.mapPoint);
      }

      map.addLayers([soils, canopy]);
    });
  </script>
</head>

<body class="claro">
  <div id="map"></div>
</body>

</html>

View solution in original post

0 Kudos
8 Replies
TimWitt2
MVP Alum

Ryan,

when you do this it doesn't give you the option within the popup window to flip through all the layers? There should be a little arrow on the upper right.

Tim

0 Kudos
TimWitt2
MVP Alum
RyanSellman
Occasional Contributor II

Hi Tim,

Thanks for the response.  When the popup is displayed, I can only flip through features within the one layer - in this case, the soilsFeatureLayer.  Selections are made on the other layers, but their popups do not display.

I have referenced that sample before but the issue with using it in my app is the user could potentially identify layers from multiple map services.  Trying to figure out the best way to handle that scenario.


Ryan

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Ryan,

  Here is a sample that demos how to do that with your data (Coding style change to AMD)

<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <!--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>Popup</title>

  <link rel="stylesheet" href="http://js.arcgis.com/3.12/dijit/themes/claro/claro.css">
  <link rel="stylesheet" href="http://js.arcgis.com/3.12/esri/css/esri.css">
  <style>
    html,
    body,
    #map {
      padding: 0;
      margin: 0;
      height: 100%;
    }
  </style>

  <script src="http://js.arcgis.com/3.12/"></script>
  <script>
    var map;
    require([
        "esri/map",
        "esri/dijit/Popup", "esri/dijit/PopupTemplate",
        "esri/layers/FeatureLayer", "esri/symbols/SimpleLineSymbol",
        "esri/symbols/SimpleFillSymbol", "esri/Color",
        "dojo/dom-class", "dojo/dom-construct", "dojo/on",
        "esri/tasks/query", "esri/geometry/Extent",
        "dojo/domReady!"
      ], function (
      Map,
      Popup, PopupTemplate,
      FeatureLayer, SimpleLineSymbol,
      SimpleFillSymbol, Color,
      domClass, domConstruct, on, Query, Extent
    ) {

      var popup = new Popup({}, domConstruct.create("div"));


      map = new Map("map", {
        basemap: "gray",
        zoom: 4,
        infoWindow: popup,
        extent: new Extent({xmin:-9093667.253259916,ymin:4998534.567771332,xmax:-9059993.366364839,ymax:5064387.406860692,spatialReference:{wkid:54032}})
      });

      var soiltemplate = new PopupTemplate({
        title: "Soil"
      });

      var soils = "http://summitmaps.summitoh.net/arcgis/rest/services/Environmental_Mercator/MapServer/2";
      soilsFeatureLayer = new FeatureLayer(soils, {
        mode: FeatureLayer.MODE_SELECTION,
        visible: true,
        outFields: ["*"],
        infoTemplate: soiltemplate
      });
      var symbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_NULL, new SimpleLineSymbol(SimpleFillSymbol.STYLE_SOLID, new Color([100, 100, 100]), 2), new Color([0, 0, 255, 0.20]));
      soilsFeatureLayer.setSelectionSymbol(symbol);

      var canopytemplate = new PopupTemplate({
        title: "Canopy"
      });

      var canopy = "http://summitmaps.summitoh.net/arcgis/rest/services/Environmental_Mercator/MapServer/5";
      canopyFeatureLayer = new FeatureLayer(canopy, {
        mode: FeatureLayer.MODE_SELECTION,
        visible: true,
        outFields: ["*"],
        infoTemplate: canopytemplate
      });
      var symbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_NULL, new SimpleLineSymbol(SimpleFillSymbol.STYLE_SOLID, new Color([100, 100, 100]), 2), new Color([0, 0, 255, 0.20]));
      canopyFeatureLayer.setSelectionSymbol(symbol);

      //var clickEvent = connect.connect(map, "onClick", selectFeatures);
      map.on('click', selectFeatures);

      function pointToExtent(map, point, toleranceInPixel) {
        var pixelWidth = map.extent.getWidth() / map.width;
        var toleranceInMapCoords = toleranceInPixel * pixelWidth;
        return new Extent(point.x - toleranceInMapCoords,
          point.y - toleranceInMapCoords,
          point.x + toleranceInMapCoords,
          point.y + toleranceInMapCoords,
          map.spatialReference);
      }

      function selectFeatures(evt) {
        var query = new Query();
        query.geometry = pointToExtent(map, evt.mapPoint, 2);
        var deferredCanopy = canopyFeatureLayer.selectFeatures(query, FeatureLayer.SELECTION_NEW);
        var deferredSoil = soilsFeatureLayer.selectFeatures(query, FeatureLayer.SELECTION_NEW);
        map.infoWindow.setFeatures([deferredSoil, deferredCanopy]);
        map.infoWindow.show(evt.mapPoint);
      }

      map.addLayers([soils, canopy]);
    });
  </script>
</head>

<body class="claro">
  <div id="map"></div>
</body>

</html>
0 Kudos
RyanSellman
Occasional Contributor II

Robert,

That's it!  Thank you so much for the help!

Ryan

0 Kudos
RyanSellman
Occasional Contributor II

Robert,

I ran into another issue related to this thread so I am going to post here...

With your sample, I can select features from multiple layers and push all results to the infoWindow - this solved my initial problem.  However taking it a step further, I ultimately want to let the user select the layers they want to ID from a list.  In the below sample I have radio buttons set up in HTML giving the user the option to ID all layers or just a certain layer:

HTML:

<div id="identifyContent" class="widgetContent">
  Identify from:
  <form id="layerList">
  <input type="radio" name="layer1" id="all" value="all" checked>All Layers
  <br>
  <input type="radio" name="layer2" id="soils" value="soils" >Soils
  <br>
  <input type="radio" name="layer3" id="canopy" value="canopy">Canopy
  </form>
  </div>

JS:

map.on('click', selectFeatures);

  function selectFeatures(evt){

  function pointToExtent (map, point, toleranceInPixel) {
   var pixelWidth = map.extent.getWidth() / map.width;
   var toleranceInMapCoords = toleranceInPixel * pixelWidth;
   return new Extent(point.x - toleranceInMapCoords,
  point.y - toleranceInMapCoords,
  point.x + toleranceInMapCoords,
  point.y + toleranceInMapCoords,
  map.spatialReference);
  }

  var query = new esri.tasks.Query();
  query.geometry = pointToExtent(map, evt.mapPoint, 2);


  if (document.getElementById("canopy").checked === true) {

  var deferredCanopy = canopyFeatureLayer.selectFeatures(query, esri.layers.FeatureLayer.SELECTION_NEW);


  } else if (document.getElementById("soils").checked === true) {

  var deferredSoil = soilsFeatureLayer.selectFeatures(query, esri.layers.FeatureLayer.SELECTION_NEW);


  } else if (document.getElementById("all").checked === true) {

  var deferredSoil = soilsFeatureLayer.selectFeatures(query, esri.layers.FeatureLayer.SELECTION_NEW);
  var deferredCanopy = canopyFeatureLayer.selectFeatures(query, esri.layers.FeatureLayer.SELECTION_NEW);

  }
  map.infoWindow.setFeatures([deferredSoil, deferredCanopy]);
  map.infoWindow.show(evt.mapPoint);
   
  }

This of course only works when the "All Layers" button is selected, but does not when its querying just one layer.  What I think I need to do is dynamically change whats passed into the array here based on what radio button is selected:

 map.infoWindow.setFeatures([deferredSoil, deferredCanopy]);

Do you have any ideas on how to make this work?

Thanks again for any help you can provide!

Ryan

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Ryan,

   Sure start by creating an empty array called deffereds or something and then use an if statement to check which radio button is selected and if value === "All Layers" then deffereds.push(deferredSoil); and deffereds.push(deferredCanopy); then add code for the other two posibilities and in the map infoWindow stuff have this instead

map.infoWindow.setFeatures(deffereds);

RyanSellman
Occasional Contributor II

Robert,

Thank you!  With your help I think I finally have it working the way I want it to now.  I added another layer to mix, switched from radio buttons to a checkbox for each layer and altered my condition statements to allow for multiple layers being checked at one time.  Here is the updated, working code in case someone else needs a hand with something similar down the road:

HTML:

<div id="identifyContent" class="widgetContent">
  Identify from:
  <br>
  <input id='soilsCheckbox' type='checkbox' /><label for='checkbox'>Soils</label>
  <br>
  <input id='floodplainCheckbox' type='checkbox' /><label for='checkbox'>Floodplains</label>
  <br>
  <input id='canopyCheckbox' type='checkbox' /><label for='checkbox'>Canopy</label>
  <br>
  <input id='allCheckbox' type='checkbox' /><label for='checkbox'>All Layers</label>
  </div>

JS:

var deffereds = [];


map.on('click', selectFeatures);


function selectFeatures(evt) {


    function pointToExtent(map, point, toleranceInPixel) {
        var pixelWidth = map.extent.getWidth() / map.width;
        var toleranceInMapCoords = toleranceInPixel * pixelWidth;
        return new Extent(point.x - toleranceInMapCoords,
            point.y - toleranceInMapCoords,
            point.x + toleranceInMapCoords,
            point.y + toleranceInMapCoords,
            map.spatialReference);
    }


    var query = new esri.tasks.Query();
    query.geometry = pointToExtent(map, evt.mapPoint, 2);




    if (dojo.byId('canopyCheckbox').checked === true) {
        var deferredCanopy = canopyFeatureLayer.selectFeatures(query, esri.layers.FeatureLayer.SELECTION_NEW);
        deffereds.push(deferredCanopy);


    } else if (dojo.byId('canopyCheckbox').checked === false) {


        alert("DO NOTHING for canopy");


    }


    if (dojo.byId('floodplainCheckbox').checked === true) {


        var deferredFloodplain = floodplainFeatureLayer.selectFeatures(query, esri.layers.FeatureLayer.SELECTION_NEW);
        deffereds.push(deferredFloodplain);


    } else if (dojo.byId('floodplainCheckbox').checked === false) {


        alert("DO NOTHING for floodplains");


    }


    if (dojo.byId('soilsCheckbox').checked === true) {


        var deferredSoil = soilsFeatureLayer.selectFeatures(query, esri.layers.FeatureLayer.SELECTION_NEW);
        deffereds.push(deferredSoil);


    } else if (dojo.byId('soilsCheckbox').checked === false) {


        alert("DO NOTHING for soils");


    }


    if (dojo.byId('allCheckbox').checked === true) {


        var deferredSoil = soilsFeatureLayer.selectFeatures(query, esri.layers.FeatureLayer.SELECTION_NEW);
        var deferredCanopy = canopyFeatureLayer.selectFeatures(query, esri.layers.FeatureLayer.SELECTION_NEW);
        var deferredFloodplain = floodplainFeatureLayer.selectFeatures(query, esri.layers.FeatureLayer.SELECTION_NEW);


        deffereds.push(deferredSoil);
        deffereds.push(deferredCanopy);
        deffereds.push(deferredFloodplain);


    } else if (dojo.byId('allCheckbox').checked === false) {


        alert("DO NOTHING for all");


    }


    map.infoWindow.setFeatures(deffereds);
    map.infoWindow.show(evt.mapPoint);


}






















































Thanks again for all of your help!!

Ryan