Passing URL Parameters to Query Feature Layers

1439
5
07-12-2020 02:52 AM
JoshHarris
Occasional Contributor

Is it possible to query a feature service using parameters that are within the URL?

My scenario is that is a user scans a QR code on a mobile device, this then launches a webpage with JS map in it, and it then zooms in on the feature relating to the QR code they have scanned. This scenario is similar to what can be achieved in WebApp Builder.

TIA

Tags (3)
0 Kudos
5 Replies
Egge-JanPollé1
MVP Regular Contributor

Hi Josh Harris,

Yes, this is possible :)

Please see the example below using the URLSearchParams interface.

It will read the municipality name from the url and zoom in to the relevant municipality.

HTH,

Egge-Jan

Just 3 examples:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
  <title>Aan de slag met ArcGIS JavaScript - Query FeatureLayer met URL Parameters</title>
  <link rel="stylesheet" href="https://js.arcgis.com/4.16/esri/css/main.css">
  <script src="https://js.arcgis.com/4.16/"></script>
  <style>
    html, body, #viewDiv {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
    }
  </style>
  <script>  
      require([
        "esri/Map",
        "esri/geometry/Point",
        "esri/views/MapView",
        "esri/layers/FeatureLayer",
        "esri/widgets/LayerList"
      ], function(Map, Point, MapView, FeatureLayer, LayerList) {

      var map = new Map({
        basemap: {
          portalItem: {
            id: "7aea6fa913a94176a1074edb40690318" // Topo RD
          }
        }
      });

      var popupTemplate = { // autocasts as new PopupTemplate()
        title: "Gemeente {Gemeentenaam}",
        content: "Gemeentecode {GM_Code}"
      };

      var renderer = {
        type: "simple",  // autocasts as new SimpleRenderer()
        symbol: {
          type: "simple-fill",  // autocasts as new SimpleFillSymbol()
          style: "none", // The polygon has no fill
          outline: {  // autocasts as new SimpleLineSymbol()
            width: 1.5,
            color: "#F5B041" // Hex Color Code
          }
        }
      };


      if ('URLSearchParams' in window) { // Feature detection (URLSearchParams is not supported by Internet Explorer)
        var url = new URL(document.URL);
        var search_params = url.searchParams;
        if(search_params.has('m')) {
          var municipality = search_params.get('m');
          var expr = "Gemeentenaam  = '" + municipality + "'";
        } else {
          var municipality = "";
          var expr = "1=1";
        }
      };

      var municipalityLayer = new FeatureLayer({
        url: "https://services.arcgis.com/nSZVuSZjHpEZZbRo/arcgis/rest/services/Bestuurlijke_Grenzen_Gemeenten_2019/FeatureServer/0",
        definitionExpression: expr,
        title: "Gemeenten " + municipality,
        minScale: 5000000,
        popupTemplate: popupTemplate,
        renderer: renderer
      });

      map.add(municipalityLayer);

	  var view = new MapView({
	    spatialReference: 28992, 
	    container: "viewDiv",
	    map: map,
	    center: new Point({x: 155000, y: 463000, spatialReference: 28992}),
	    zoom: 3
	  });

      var layerList = new LayerList({
        view: view
      });

      view.ui.add(layerList, {
        position: "top-right"
      });

      municipalityLayer
        .when(function() {
          return municipalityLayer.queryExtent();
        })
        .then(function(response) {
          view.goTo(response.extent);
        });
    });
  </script>
</head>
<body>
  <div id="viewDiv"></div>
</body>
</html>‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
JoshHarris
Occasional Contributor

Hi Egge-Jan,

That is perfect, exactly what I'm after! Unfortunately, I'm a bit stuck; I can get the map to filter the feature and only show it on the map, but I can't get it to do the zoom bit. Any ideas as to why this would be?

0 Kudos
Egge-JanPollé1
MVP Regular Contributor

Hi Josh Harris,

For the zoom bit, please have a look at this example: Zoom to extent of all features | ArcGIS API for JavaScript 4.16 

As you can see in my example, 1) a single municipality is filtered out, 2) this municipality is added to the map, 3) the extent of this layer is queried and then you can zoom in with view.goTo().

// When the layer is loaded, query for the extent
// of all features in the layer. Then set the view's
// extent to the returned extent of all features.

layer
  .when(function() {
    return layer.queryExtent();
  })
  .then(function(response) {
    view.goTo(response.extent);
  });

HTH,

Egge-Jan

0 Kudos
JoshHarris
Occasional Contributor

Hi Egge-Jan, the issue seems to be when I change the spatial reference from 28992 to 3395. Please see below (fyi, I've starred out the feature service url).

<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8">
 <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
 <title>Aan de slag met ArcGIS JavaScript - Query FeatureLayer met URL Parameters</title>
 <link rel="stylesheet" href="https://js.arcgis.com/4.16/esri/css/main.css">
 <script src="https://js.arcgis.com/4.16/"></script>
 <style>
 html, body, #viewDiv {
 padding: 0;
 margin: 0;
 height: 100%;
 width: 100%;
 }
 </style>
 <script> 
 require([
 "esri/Map",
 "esri/geometry/Point",
 "esri/views/MapView",
 "esri/layers/FeatureLayer",
 "esri/widgets/LayerList"
 ], function(Map, Point, MapView, FeatureLayer, LayerList) {
var map = new Map({
 basemap: "topo-vector"
 });
var popupTemplate = { // autocasts as new PopupTemplate()
 title: "ID {map16_tree_id}",
 content: "ID {map16_tree_id}"
 };
var renderer = {
 type: "simple", // autocasts as new SimpleRenderer()
 symbol: {
 type: "simple-fill", // autocasts as new SimpleFillSymbol()
 style: "none", // The polygon has no fill
 outline: { // autocasts as new SimpleLineSymbol()
 width: 1.5,
 color: "#F5B041" // Hex Color Code
 }
 }
 };

 if ('URLSearchParams' in window) { // Feature detection (URLSearchParams is not supported by Internet Explorer)
 var url = new URL(document.URL);
 var search_params = url.searchParams;
 if(search_params.has('m')) {
 var municipality = search_params.get('m');
 var expr = "map16_tree_id = '" + municipality + "'";
 } else {
 var municipality = "";
 var expr = "1=1";
 }
 };
var municipalityLayer = new FeatureLayer({
 url: "************",
 definitionExpression: expr,
 title: municipality,
 minScale: 5000000, 
 popupTemplate: popupTemplate,
 renderer: renderer
 });
map.add(municipalityLayer);
var view = new MapView({
 spatialReference: 3395, 
 container: "viewDiv",
 map: map,
 center: new Point({x: -2.621237, y: 51.477442, spatialReference: 3395}),
 zoom: 19
 });
var layerList = new LayerList({
 view: view
 });
view.ui.add(layerList, {
 position: "top-right"
 });

 municipalityLayer.when(function() {
 return municipalityLayer.queryExtent();
 })
 .then(function(response) {
 view.goTo(response.extent);
 });
 });
 </script>
</head>
<body>
 <div id="viewDiv"></div>
</body>
</html>‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
Egge-JanPollé1
MVP Regular Contributor

Hi Josh Harris,

OK - I just provided an example to show how you can pass url parameters to query feature layers. (And yes, I did use some Dutch data in this example, so that's why the view has 28992 as a spatial reference.)

It is up to you now to apply this workflow to your own data. I am unable to test your code, because you starred out quite an essential part, i.e. the input feature service url. So I can't tell what is going well and what is going wrong.

What browser are you using? Do you see any error messages in the console?

Please let us know how you managed to solve the issue.

Egge-Jan

0 Kudos