ArcGIS JS Api 4 multiple filters working together

486
2
Jump to solution
11-14-2020 09:22 AM
rcwisc
by
New Contributor II

Hello,

 

I am using ArcGIS API 4 and am trying to combine filters. I have a featureLayer that is filtered depending on the zoom level and then can also be filtered with a dropdown but the problem is that these filters override each other. I would like them to be dependent on one another. If the zoom filter is set on the layer, it should remain applied if the dropdown menu is set. I can't find an example of how to to set this up. Any help would be highly appreciated. 

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
    <link rel="stylesheet" href="https://js.arcgis.com/4.17/esri/css/main.css">
    <script src="https://js.arcgis.com/4.17/"></script>
    <title>UWM Historical Nautical Charts</title>
    <style>
      html, body, #viewDiv {
        padding: 0;
        margin: 0;
        height: 100%;
        width: 100%;
      }
    </style>
    <script>
  require(["esri/Map", "esri/views/MapView", "esri/layers/FeatureLayer", "esri/geometry/Extent"], function(
  Map,
  MapView,
  FeatureLayer,
  Extent
) {

  // Create a style for the chartsLayer
  var renderer = {
  type: "simple",  // autocasts as new SimpleRenderer()
  symbol: {
    type: "simple-fill",  // autocasts as new SimpleFillSymbol()
    color: [ 255, 128, 0, 0.5 ],
    outline: {  // autocasts as new SimpleLineSymbol()
      width: 1,
      color: "white"
    }
  }
  };

  // Create a FeatureLayer
  var chartsLayer = new FeatureLayer({
    url: "https://webgis.uwm.edu/arcgisuwm/rest/services/AGSL/agsl_nautical/MapServer/0",
    outFields: ["*"], // Return all fields so it can be queried client-side
    renderer: renderer
  });

  // Create the Map and add the featureLayer defined above
  map = new Map({
    basemap: "oceans",
    layers: [chartsLayer]
  });

  // Create the MapView
  var view = new MapView({
    container: "viewDiv",
    map: map,
    center: [0,0],    
    zoom: 2
  });

  // setup the contraints of the map
  view.constraints = {
  geometry: {            // Constrain lateral movement to the entire globe with no repeat
    type: "extent",
    xmin: -90,
    ymin: -180,
    xmax: 90,
    ymax: 180
  },
  minZoom: 2,          
  rotationEnabled: false // Disables map rotation
};

  // Create a template for the popup
  var template = {
  // autocasts as new PopupTemplate()
  title: "{title}",
  content: [
    {
      type: "fields",
      fieldInfos: [
        {
          fieldName: "label",
          label: "label"
        },
        {
          fieldName: "west",
          label: "West"
        },
        {
          fieldName: "east",
          label: "East"
        },
        {
          fieldName: "north",
          label: "North"
        },
        {
          fieldName: "south",
          label: "South"
        },
        {
          fieldName: "scale",
          label: "Scale"
        }
      ]
    }
  ]
};

// Set the popup template on the layer
chartsLayer.popupTemplate = template;

function setFeatureLayerFilter(expression) {
  chartsLayer.definitionExpression = expression;
}
// The filter for the page load map view
// Only show small scale series
setFeatureLayerFilter("Shape_Area >= 9463642202000" );

//setFeatureLayerFilter("scale < 698000" );
// Exclude map scales according to the zoom level
// Use 'Shape_Area' because scale information might be missing for some charts     
view.watch("zoom", function(newValue) {
  if (newValue <= 2) {    
    setFeatureLayerFilter("Shape_Area >= 9463642202000" ); 
  } else if (newValue >= 4) {
    setFeatureLayerFilter("Shape_Area <= 946364220200" );
  }

  console.log("scale property changed: ", newValue);
});

// Query the layer based on the chart series
var sqlExpressions = [
  "datePub = 1911",
  "datePub = 1912"  
];

var selectFilter = document.createElement("select");
selectFilter.setAttribute("class", "esri-widget esri-select");
selectFilter.setAttribute(
  "style",
  "width: 275px; font-family: Avenir Next W00; font-size: 1em;"
);

sqlExpressions.forEach(function (sql) {
  var option = document.createElement("option");
  option.value = sql;
  option.innerHTML = sql;
  selectFilter.appendChild(option);
});

view.ui.add(selectFilter, "top-right");

 selectFilter.addEventListener('change', function (event) {
        setFeatureLayerFilter(event.target.value);
      });

});




  </script>
    </script>
  </head>
  <body>
    <div id="viewDiv"></div>
  </body>
</html>

 

0 Kudos
1 Solution

Accepted Solutions
Giannalogy
New Contributor III

Hi there, 

You have to make each of your listener functions listen to each other. 

Here's what I did to make it work (nb I changed the dates to 1856 and 1921 because they were easier to see):

 

function setFeatureLayerFilter(expression) {
    chartsLayer.definitionExpression = expression;
}

// The filter for the page load map view
// Only show small scale series
setFeatureLayerFilter("Shape_Area >= 9463642202000 AND datepub = 1856");

//setFeatureLayerFilter("scale < 698000" );
// Exclude map scales according to the zoom level
// Use 'Shape_Area' because scale information might be missing for some charts     
view.watch("zoom", function(newValue) {
    switch (selectFilter.value) {
        case "datePub = 1856":
            if (newValue <= 2) {
                setFeatureLayerFilter("Shape_Area >= 9463642202000 AND datePub = 1856");
            } else if (newValue >= 4) {
                setFeatureLayerFilter("Shape_Area <= 946364220200 AND datePub = 1856");
            }
            break;
        case "datePub = 1921":
            if (newValue <= 2) {
                setFeatureLayerFilter("Shape_Area >= 9463642202000 AND datePub = 1921");
            } else if (newValue >= 4) {
                setFeatureLayerFilter("Shape_Area <= 946364220200 AND datePub = 1921");
            }
            break;
    }
});

// Query the layer based on the chart series
var sqlExpressions = [
    "datePub = 1856",
    "datePub = 1921"
];

var selectFilter = document.createElement("select");
selectFilter.setAttribute("class", "esri-widget esri-select");
selectFilter.setAttribute(
    "style",
    "width: 275px; font-family: Avenir Next W00; font-size: 1em;"
);

sqlExpressions.forEach(function(sql) {
    var option = document.createElement("option");
    option.value = sql;
    option.innerHTML = sql;
    selectFilter.appendChild(option);
});

view.ui.add(selectFilter, "top-right");

selectFilter.addEventListener('change', function(event) {
    if (view.zoom >= 2) {
        setFeatureLayerFilter("Shape_Area <= 9463642202000 AND" + event.target.value);
    } else {
        setFeatureLayerFilter("Shape_Area >= 9463642202000 AND" + event.target.value);
    }
});

 

 

View solution in original post

2 Replies
Giannalogy
New Contributor III

Hi there, 

You have to make each of your listener functions listen to each other. 

Here's what I did to make it work (nb I changed the dates to 1856 and 1921 because they were easier to see):

 

function setFeatureLayerFilter(expression) {
    chartsLayer.definitionExpression = expression;
}

// The filter for the page load map view
// Only show small scale series
setFeatureLayerFilter("Shape_Area >= 9463642202000 AND datepub = 1856");

//setFeatureLayerFilter("scale < 698000" );
// Exclude map scales according to the zoom level
// Use 'Shape_Area' because scale information might be missing for some charts     
view.watch("zoom", function(newValue) {
    switch (selectFilter.value) {
        case "datePub = 1856":
            if (newValue <= 2) {
                setFeatureLayerFilter("Shape_Area >= 9463642202000 AND datePub = 1856");
            } else if (newValue >= 4) {
                setFeatureLayerFilter("Shape_Area <= 946364220200 AND datePub = 1856");
            }
            break;
        case "datePub = 1921":
            if (newValue <= 2) {
                setFeatureLayerFilter("Shape_Area >= 9463642202000 AND datePub = 1921");
            } else if (newValue >= 4) {
                setFeatureLayerFilter("Shape_Area <= 946364220200 AND datePub = 1921");
            }
            break;
    }
});

// Query the layer based on the chart series
var sqlExpressions = [
    "datePub = 1856",
    "datePub = 1921"
];

var selectFilter = document.createElement("select");
selectFilter.setAttribute("class", "esri-widget esri-select");
selectFilter.setAttribute(
    "style",
    "width: 275px; font-family: Avenir Next W00; font-size: 1em;"
);

sqlExpressions.forEach(function(sql) {
    var option = document.createElement("option");
    option.value = sql;
    option.innerHTML = sql;
    selectFilter.appendChild(option);
});

view.ui.add(selectFilter, "top-right");

selectFilter.addEventListener('change', function(event) {
    if (view.zoom >= 2) {
        setFeatureLayerFilter("Shape_Area <= 9463642202000 AND" + event.target.value);
    } else {
        setFeatureLayerFilter("Shape_Area >= 9463642202000 AND" + event.target.value);
    }
});

 

 

View solution in original post

rcwisc
by
New Contributor II

Sorry to be late on getting back to you on this. This works great, thank you very much. 

0 Kudos