How to setDefinitionExpression on FeatureLayer in web map? (v3.30)

781
2
Jump to solution
11-04-2019 11:50 AM
JimBarry
Esri Regular Contributor

Attn: JS API 3.x

Anyone have a sample for setting a definition expression on a feature layer in a web map? 

I'd like to give my end-user a multiselect pick list of unique values in a column and have the layer within the web map filter its features based on that where clause.

Here is an example of how it works when you load the FeatureLayer through code directly: https://codepen.io/JimBarry/pen/eYYyBya 

But not when the layer is inside a web map.

Thanks!

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Esteemed Contributor

Jim,

   Here is a solution if you have not got one already.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
    <title>Dojo MultiSelect Dijit with ArcGIS JS API 3x v1</title>
    
    <link rel="stylesheet" href="https://js.arcgis.com/3.30/esri/css/esri.css" />
    <script src="https://js.arcgis.com/3.30/"></script>

    <style>
      body {
        margin: 0;
        padding: 0;
        width: 100%;
        height: 100%;
      }
      #bannerDiv {
        width: 100%;
        height: 190px;
        background-color: #FFCCCC;
        text-align: center;
        padding: 5px;
      }
      #viewDiv {
        position: absolute;
        width: 100%;
        height: calc(100% - 180px);
      }
    </style>

    <script>
      require([
        "esri/map",
        "esri/layers/FeatureLayer",
        "dijit/form/MultiSelect",
        "esri/arcgis/utils",
        "dojo/dom",
        "dojo/on"  
      ], function(Map, FeatureLayer, MultiSelect, arcgisUtils, dom, on) {
        let borrosLyr = null;
        arcgisUtils.createMap("1d1229a2045940e59730a18bad82c0aa", "viewDiv").then(function (response) {
          var map = response.map;
          var webMapLayers = arcgisUtils.getLayerList(response);
          webMapLayers.some(function(lyr){
            return lyr.title === 'NYC_Community_Districts' ? ((borrosLyr = lyr.layer), true): false
          });
        });
        
        function applyDefinition() {
          const selected = document.querySelectorAll('#boros option:checked');
          const values = Array.from(selected).map(el => el.value);

          var strDefinitionExpression = "boroname IN (";

          // build the where clause definition expression string based on user input
          var vals = [];
          for (i=0; i<values.length; i++) {
            vals.push("'" + values[i] + "'");
          }
          var valsStr = vals.join();
          strDefinitionExpression += valsStr + ")";
          console.info(strDefinitionExpression);
          borrosLyr.setDefinitionExpression(strDefinitionExpression);
        } // end of function applyQueryDef()

        function clearDefinition() {
          var elemMultiSelect = dom.byId("boros");

          // deselect all elements in the multiselect box UI
          for (i=0; i<elemMultiSelect.length; i++) {
            elemMultiSelect[i].selected = false;
          }
          
          // clear out the definition expression so that all features draw
          borrosLyr.setDefinitionExpression("");

        } // end of function clearQueryDef()

      // BUTTON CLICK EVENTS
        on(dom.byId("btnApplyDefinition"), "click", applyDefinition);
        on(dom.byId("btnClearDefinition"), "click", clearDefinition);
    
      }); //end of require
    </script>
  </head>

  <body>
    
    <div id="bannerDiv">
      <h4>How to use a dojo/MultiSelect box to apply a layer definition expression</h4>
      <h5>Use click, shift-click, ctrl-click to multi-select values, then click APPLY.</h5>

      <select data-dojo-type="dijit/form/MultiSelect" 
              multiple="true" style="height:80px;width:100px" 
              id="boros" name="boros" size="4">
        <option value="Manhattan">Manhattan</option>
        <option value="Bronx">Bronx</option>
        <option value="Brooklyn">Brooklyn</option>
        <option value="Queens">Queens</option>        
        <option value="Staten Island">Staten Island</option>
      </select>      
      <button class="btn" id="btnApplyDefinition">Apply</button>
      <button class="btn" id="btnClearDefinition">Clear</button>

    </div>
  
    <div id="viewDiv"></div>
      
  </body>

</html>

View solution in original post

2 Replies
RobertScheitlin__GISP
MVP Esteemed Contributor

Jim,

   Here is a solution if you have not got one already.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
    <title>Dojo MultiSelect Dijit with ArcGIS JS API 3x v1</title>
    
    <link rel="stylesheet" href="https://js.arcgis.com/3.30/esri/css/esri.css" />
    <script src="https://js.arcgis.com/3.30/"></script>

    <style>
      body {
        margin: 0;
        padding: 0;
        width: 100%;
        height: 100%;
      }
      #bannerDiv {
        width: 100%;
        height: 190px;
        background-color: #FFCCCC;
        text-align: center;
        padding: 5px;
      }
      #viewDiv {
        position: absolute;
        width: 100%;
        height: calc(100% - 180px);
      }
    </style>

    <script>
      require([
        "esri/map",
        "esri/layers/FeatureLayer",
        "dijit/form/MultiSelect",
        "esri/arcgis/utils",
        "dojo/dom",
        "dojo/on"  
      ], function(Map, FeatureLayer, MultiSelect, arcgisUtils, dom, on) {
        let borrosLyr = null;
        arcgisUtils.createMap("1d1229a2045940e59730a18bad82c0aa", "viewDiv").then(function (response) {
          var map = response.map;
          var webMapLayers = arcgisUtils.getLayerList(response);
          webMapLayers.some(function(lyr){
            return lyr.title === 'NYC_Community_Districts' ? ((borrosLyr = lyr.layer), true): false
          });
        });
        
        function applyDefinition() {
          const selected = document.querySelectorAll('#boros option:checked');
          const values = Array.from(selected).map(el => el.value);

          var strDefinitionExpression = "boroname IN (";

          // build the where clause definition expression string based on user input
          var vals = [];
          for (i=0; i<values.length; i++) {
            vals.push("'" + values[i] + "'");
          }
          var valsStr = vals.join();
          strDefinitionExpression += valsStr + ")";
          console.info(strDefinitionExpression);
          borrosLyr.setDefinitionExpression(strDefinitionExpression);
        } // end of function applyQueryDef()

        function clearDefinition() {
          var elemMultiSelect = dom.byId("boros");

          // deselect all elements in the multiselect box UI
          for (i=0; i<elemMultiSelect.length; i++) {
            elemMultiSelect[i].selected = false;
          }
          
          // clear out the definition expression so that all features draw
          borrosLyr.setDefinitionExpression("");

        } // end of function clearQueryDef()

      // BUTTON CLICK EVENTS
        on(dom.byId("btnApplyDefinition"), "click", applyDefinition);
        on(dom.byId("btnClearDefinition"), "click", clearDefinition);
    
      }); //end of require
    </script>
  </head>

  <body>
    
    <div id="bannerDiv">
      <h4>How to use a dojo/MultiSelect box to apply a layer definition expression</h4>
      <h5>Use click, shift-click, ctrl-click to multi-select values, then click APPLY.</h5>

      <select data-dojo-type="dijit/form/MultiSelect" 
              multiple="true" style="height:80px;width:100px" 
              id="boros" name="boros" size="4">
        <option value="Manhattan">Manhattan</option>
        <option value="Bronx">Bronx</option>
        <option value="Brooklyn">Brooklyn</option>
        <option value="Queens">Queens</option>        
        <option value="Staten Island">Staten Island</option>
      </select>      
      <button class="btn" id="btnApplyDefinition">Apply</button>
      <button class="btn" id="btnClearDefinition">Clear</button>

    </div>
  
    <div id="viewDiv"></div>
      
  </body>

</html>
JimBarry
Esri Regular Contributor

Perfect!! Thanks Robert!!

No I hadn't figured it out yet. I had never really learned how things work at 3x, so I get stumped from time to time. Seems the key I was missing was:

var webMapLayers = arcgisUtils.getLayerList(response);

...within the .createMap() block.

Because from your code, it seems that once you have the layer out of that layer list, then .setDefinitionExpression() works the same.

Oh, and yeah, the part about building the expression with "IN" rather than chaining "OR"s, just better. My head wasn't on that part of the problem, so thanks for that too. Also the array.join() method, very handy.

Haven't spoken in quite a while. I hope things are going well. :)

0 Kudos