This question is a continuation of my last one: Query Features by Category and Keyword
The app so far has two drop-downs. The user can query by categories and query by keywords.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<title>Recycling Map</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.15/esri/themes/light/main.css" />
<script src="https://js.arcgis.com/4.15/"></script>
<style>
html,
body,
#viewDiv {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
#infoDiv {
background-color: white;
color: black;
padding: 6px;
width: 440px;
}
#titleDiv {
padding: 10px;
}
#titleText {
font-size: 20pt;
font-weight: 60;
padding-bottom: 10px;
}
#results {
font-weight: bolder;
padding-top: 10px;
}
#category,
#keyword {
margin-top: 8px;
margin-bottom: 8px;
}
</style>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/FeatureLayer",
"esri/layers/GraphicsLayer",
"esri/geometry/geometryEngine",
"esri/Graphic"
], function (
Map,
MapView,
FeatureLayer,
GraphicsLayer,
geometryEngine,
Graphic
) {
var catTypeSelect = document.getElementById("category");
var keyTypeSelect = document.getElementById("keyword");
var filterButton = document.getElementById("SelectBtn");
var recycleLayer = new FeatureLayer({
portalItem: {
id: "227061be60a14cc89946a978b440d227"
},
outFields: ["*"],
visible: false
});
var resultsLayer = new GraphicsLayer();
var map = new Map({
basemap: "dark-gray",
layers: [recycleLayer, resultsLayer]
});
var view = new MapView({
container: "viewDiv",
map: map,
center: [-87.95, 41.47],
zoom: 10
});
view.ui.add("infoDiv", "top-left");
view
.when(function () {
return recycleLayer.when(function () {
var query = recycleLayer.createQuery();
return recycleLayer.queryFeatures(query);
});
})
.then(getValues)
.then(getUniqueValues)
.then(addToSelect)
function getValues(response) {
var features = response.features;
var values = features.map(function (feature) {
return {
USER_Categ: feature.attributes.USER_Categ,
USER_Keywo: feature.attributes.USER_Keywo
}
});
return values;
}
function getUniqueValues(values) {
var uniqueKeyValues = [];
var uniqueCatValues = [];
values.forEach(function (item, i) {
var keyVal = item.USER_Keywo.split(";");
var catVal = item.USER_Categ.split(";");
catVal.map(function (val1) {
if (
(uniqueCatValues.length < 1 || uniqueCatValues.indexOf(val1) === -1) &&
val1 !== ""
) {
uniqueCatValues.push(val1);
}
});
keyVal.map(function (val2) {
if (
(uniqueKeyValues.length < 1 || uniqueKeyValues.indexOf(val2) === -1) &&
val2 !== ""
) {
uniqueKeyValues.push(val2);
}
});
});
return {
uKeyVals: uniqueKeyValues,
uCatVals: uniqueCatValues
};
}
function addToSelect(values) {
values.uCatVals.sort();
values.uCatVals.forEach(function (value) {
var option = document.createElement("option");
option.text = value;
catTypeSelect.add(option);
});
values.uKeyVals.sort();
values.uKeyVals.forEach(function (value) {
var option = document.createElement("option");
option.text = value;
keyTypeSelect.add(option);
});
return setDefinitionExpression();
}
function setDefinitionExpression() {
var sqlExp = "";
if (catTypeSelect.selectedIndex > 0) {
sqlExp += "USER_Categ LIKE '%" + catTypeSelect.options[catTypeSelect.selectedIndex].value + "%'";
}
if (keyTypeSelect.selectedIndex > 0) {
if (sqlExp === "") {
sqlExp += "USER_Keywo LIKE '%" + keyTypeSelect.options[keyTypeSelect.selectedIndex].value + "%'";
} else {
sqlExp += " AND USER_Keywo LIKE '%" + keyTypeSelect.options[keyTypeSelect.selectedIndex].value + "%'";
}
}
recycleLayer.definitionExpression = sqlExp;
if (!recycleLayer.visible) {
recycleLayer.visible = true;
}
return queryForGeometries();
}
function queryForGeometries() {
var rQuery = recycleLayer.createQuery();
return recycleLayer.queryFeatures(rQuery).then(function (response) {
rGeometries = response.features.map(function (feature) {
return feature.geometry;
});
return rGeometries;
});
}
filterButton.addEventListener("click", function () {
setDefinitionExpression();
});
view.ui.add("titleDiv", "top-right");
});
</script>
</head>
<body>
<div id="viewDiv"></div>
<div id="infoDiv" class="esri-widget">
<div id="drop-downs">
Select Category (leave blank if searching by Keyword):
<select id="category" class="esri-widget"></select>
Select Keyword:
<select id="keyword" class="esri-widget"></select>
<button id="SelectBtn" class="esri-button esri-button--secondary">Search</button>
</div>
<div id="results" class="esri-widget"></div>
</div>
<div id="titleDiv" class="esri-widget">
<div id="titleText">Green Guide</div>
<div>Easy Ways To Be More Green</div>
</div>
</body>
</html>
Now I'd like to filter the categories and keywords based on two fields in the attribute table, USER_IsRes and USER_IsBus (residential and business). The values are either TRUE or FALSE-- Feature Layer View. I'm able to use a sample and loosely get that to function with the USER_IsRes field.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no"
/>
<title>Filter features by attribute - 4.15</title>
<link
rel="stylesheet"
href="https://js.arcgis.com/4.15/esri/themes/light/main.css"
/>
<script src="https://js.arcgis.com/4.15/"></script>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
#res-filter {
height: 160px;
width: 100%;
visibility: hidden;
}
.res-item {
width: 100%;
padding: 12px;
text-align: center;
vertical-align: baseline;
cursor: pointer;
height: 40px;
}
.res-item:focus {
background-color: dimgrey;
}
.res-item:hover {
background-color: dimgrey;
}
#titleDiv {
padding: 10px;
}
#titleText {
font-size: 20pt;
font-weight: 60;
padding-bottom: 10px;
}
</style>
<script>
require([
"esri/views/MapView",
"esri/Map",
"esri/layers/FeatureLayer",
"esri/widgets/Expand"
], function (MapView, Map, FeatureLayer, Expand) {
let floodLayerView;
const layer = new FeatureLayer({
portalItem: {
id: "227061be60a14cc89946a978b440d227"
},
outFields: ["USER_IsRes"]
});
const map = new Map({
basemap: "gray-vector",
layers: [layer]
});
const view = new MapView({
map: map,
container: "viewDiv",
center: [-98, 40],
zoom: 4
});
const resNodes = document.querySelectorAll(`.res-item`);
const resElement = document.getElementById("res-filter");
resElement.addEventListener("click", filterByres);
function filterByres(event) {
const selectedres = event.target.getAttribute("data-res");
floodLayerView.filter = {
where: "USER_IsRes = '" + selectedres + "'",
};
}
view.whenLayerView(layer).then(function(layerView) {
floodLayerView = layerView;
resElement.style.visibility = "visible";
const resExpand = new Expand({
view: view,
content: resElement,
expandIconClass: "esri-icon-filter",
group: "top-left"
});
resExpand.watch("expanded", function() {
if (!resExpand.expanded) {
floodLayerView.filter = null;
}
});
view.ui.add(resExpand, "top-left");
view.ui.add("titleDiv", "top-right");
});
});
</script>
</head>
<body>
<div id="res-filter" class="esri-widget">
<div class="res-item visible-res" data-res="TRUE">True</div>
<div class="res-item visible-res" data-res="False">False</div>
</div>
<div id="viewDiv"></div>
<div id="titleDiv" class="esri-widget">
<div id="titleText">Flash Floods by res</div>
<div>Flash Flood Warnings (2002 - 2012)</div>
</div>
</body>
</html>
But, how do I incorporate the filter (preferably client side since they say it's faster) into the app? Once the user has either a keyword or category selected I want there to be a way to filter with either Residential or Business.
In the end, the selection methods should more or less mirror this page: Will County EEC Mobile Site