UMD JS API Workshop
Exercise 9 - Search with Widgets

Instructions:

In this lab you will use a Query to get specific data from a feature layer. A query allows you to make a SQL or spatial query to reache out to that REST endpoint for the feature layer and get that data.

With Querys, you are responsible for adding the resulting features to the map as graphics. You are also responsible for adding a symbol and defining the popup template used for the data.

Let's look at some Washington D.C. Metro Station data and use this query to select and symbolize the different lines!

Exercise:

1. Create HTML Select Box
First thing we need is a "select" element in our HTML with different options for each metro line.
The text that we put in here will eventually be passed back into the query, since the user has to select the line they want to view.

  <div id="viewDiv"></div>
  <!-- ADD -->
  <select id="queryDiv">
    <option selected>blue</option>
    <option>orange</option>
    <option>red</option>
    <option>silver</option>
    <option>yellow</option>
  </select>


2. Update Require
Update your require statement and function definition to include the following:

require([
  "esri/views/MapView",
  "esri/Map",
  /*** ADD ***/
  "esri/layers/FeatureLayer",
  "esri/rest/support/Query",
  "esri/symbols/SimpleMarkerSymbol"
], function(MapView, Map, FeatureLayer, Query, SimpleMarkerSymbol) {


3. Add Query
Now we're going to create a Query and attach it to the feature layer to select features from the metro stops.
Note that we never add this feature layer to the map. We don't need to since we're just using it to return graphics.
We're also going to simply return two fields from the layer, since that's all we need.

var view = new MapView({
  container: "viewDiv",
  map: map,
  center: [-77.029, 38.89],
  zoom: 10
});

//Add layer to query on
var metroLines = new FeatureLayer({
  url: "https://services.arcgis.com/hRUr1F8lE8Jq2uJo/arcgis/rest/services/Metro_Stations_Regional/FeatureServer/0"
});

//Attach query to feature layer
var query = metroLines.createQuery();
//These are the attributes we need
query.outFields = ["NAME", "LINE"];
//And we also need the geometry
query.returnGeometry = true;


4. Lots o' Functions
Next, we're defining a bunch of functions that are going to execute the query, get the features, and then add them to the default graphics layer of the view.
Notice also that we perform the "getFeatures" function with blue so that the map always starts with something there.

//Perform query when page loads
getFeatures("blue");

//Get features with query where clause
function getFeatures(theColor) {
  query.where = "LINE LIKE '%" + theColor + "%'";
  metroLines.queryFeatures(query).then(function(results) {
    addFeatures(results.features);
  })
.catch(promiseRejected);
}

//Add features as graphics
function addFeatures(features) {
  var color;
  //Color
  switch (document.getElementById("queryDiv").value) {
    case "blue":
      color = [0, 0, 255]
      break;
    case "red":
      color = [255, 0, 0]
      break;
    case "green":
      color = [0, 255, 0]
      break;
    case "orange":
      color = [255,165, 0]
      break;
    case "yellow":
      color = [255, 255, 0]
      break;
    case "silver":
      color = [190, 190, 190]
      break;
  }
  var symbol = new SimpleMarkerSymbol({
    color: color,
    size: 8,
    outline: {
      color: [ 255, 255, 255 ],
      width: 1
    }
  });
  //Set symbol and popup template
  for (var i=0; i < features.length; i++) {
    var feature = features[i];
    feature.symbol = symbol;
    feature.popupTemplate = {
      title: "{NAME}",
      content: "This is a metro stop for the {LINE} line(s)."
    }
    view.graphics.add(feature);
  }
  //Add graphics
  view.graphics.removeAll();
  view.graphics.addMany(features);
  view.goTo(features);
  view.popup.visible = false;
}


5. Add Handlers
Final step I promise! We just have to add some handlers to select the HTML element so we can change the SQL string for the query. Also, just an error handler in case the service isn't working!

//Add select element to UI
view.when(function() {
  view.ui.add(document.getElementById("queryDiv"), "top-right");
  document.getElementById("queryDiv").addEventListener("change", doQuery);
});

//Get the color from the drop down
function doQuery(e) {
  var theColor = e.target.value;
  getFeatures(theColor);
};

//Add the promise rejected function
function promiseRejected(){
  console.log("Error with query");
}

And now, after all of this, your application should look like this:






Challenges:

Oops! I left out the green line! Can you modify the HTML to include the green line and ensure that it still works with our query task?


Final Solution