Using ArcGIS API for Javascript 4, I want to create a drop-down list in the view that is dynamically populated based on the values available in a layer. When users select a value from this drop down and click a button, I want to query those features matching the value in the drop menu and have them appear on the map.
I've combined some elements from the following two tutorials for this:
https://developers.arcgis.com/javascript/latest/sample-code/tasks-query/index.html https://developers.arcgis.com/javascript/latest/sample-code/featurelayer-query/index.html
I can get the attributes to populate in the drop down list. However, clicking the button to query returns the following error message: "Promise rejected: Cannot perform query. Invalid query parameters."
I'm hoping this is just something simple I've overlooked, but I can't seem to find the issue. I am copying and pasting the complete code in case that's easiest to drop into CodePen or elsewhere to work with.
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no"/>
<title>Project viewer</title>
<style>
html,
body,
#mainViewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
#optionsDiv {
background-color: dimgray;
color: white;
padding: 10px;
width: 90%;
}
#drop-downs {
padding-bottom: 15px;
}
widget {
/* Fill in later to style drop down widget */
}
</style>
<link
rel="stylesheet"
href="https://js.arcgis.com/4.15/esri/themes/light/main.css"
/>
<script src="https://js.arcgis.com/4.15/"></script>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/Basemap",
"esri/widgets/LayerList",
"esri/layers/FeatureLayer",
"esri/PopupTemplate",
"esri/layers/GraphicsLayer",
"esri/tasks/QueryTask",
"esri/tasks/support/Query"
], function(
Map,
MapView,
Basemap,
LayerList,
FeatureLayer,
PopupTemplate,
GraphicsLayer,
QueryTask,
Query
){
var basinUrl = "https://services.arcgis.com/v01gqwM5QqNysAAi/arcgis/rest/services/Chesapeake_Bay_major_watersheds_feature/FeatureServer/0";
//* for drop down
var basinTypeSelect = document.getElementById("MajBas");
//* Define the popup content for each result
var popupTemplate = {
title: "{MajBas}",
fieldInfos: [
{
fieldName: "MajBas",
label: "Major basin"
}
]
};
// Layer - project footprints
const basinLayer = new FeatureLayer({
url: basinUrl,
outFields: ["*"],
visible: false
});
// Layer - dark nav basemap
const basemap = Basemap.fromId("streets-night-vector");
//** Point querytask to project boundary URL
var qTask = new QueryTask({
url: basinUrl
});
//** Set the query parameters to always return geometry and all fields.
//** Returning geometry allows us to display results on the map/view
var params = new Query({
returnGeometry: true,
outFields: ["*"]
});
//* GraphicsLayer for displaying results
var resultsLayer = new GraphicsLayer();
var map = new Map({
basemap : basemap,
layers: [basinLayer]
});
var mainView = new MapView({
container: "mainViewDiv",
map: map,
popup: {
highlightEnabled: false,
dockEnabled: true,
dockOptions: {
breakpoint: false,
position: "top-right"
}
},
center: [-75.325395, 40.306275],
zoom: 5
});
// add widget with drop-down options
mainView.ui.add("optionsDiv", {
position: "bottom-left"
});
//* query all features from the basin layer
mainView
.when(function () {
return basinLayer.when(function () {
var query = basinLayer.createQuery();
return basinLayer.queryFeatures(query);
document.getElementById("doBtn").addEventListener("click", doQuery);
});
})
.then(getValues)
.then(getUniqueValues)
.then(addToSelect)
.then(doQuery)
//* return an array of all the values in the
//* basin name field
function getValues(response) {
var features = response.features;
var values = features.map(function (feature) {
return feature.attributes.MajBas;
});
return values;
}
//* return an array of unique values in
//* the MajBas field of the basin layer
function getUniqueValues(values) {
var uniqueValues = [];
values.forEach(function (item, i) {
if (
(uniqueValues.length < 1 || uniqueValues.indexOf(item) === -1) &&
item !== ""
) {
uniqueValues.push(item);
}
});
return uniqueValues;
}
//* Add the unique values to the basin type
//* select element. This will allow the user
//* to filter basin by name.
function addToSelect(values) {
values.sort();
values.forEach(function (value) {
var option = document.createElement("option");
option.text = value;
basinTypeSelect.add(option);
});
}
//** Call doQuery() each time the button is clicked
mainView.when(function () {
mainView.ui.add("optionsDiv", "bottom-left");
document.getElementById("doBtn").addEventListener("click", doQuery);
});
//**
var attributeName = document.getElementById("MajBas");
// Executes each time the button is clicked
function doQuery() {
// Clear the results from a previous query
resultsLayer.removeAll();
// Build new query
params.where =
"MajBas =" + attributeName.value;
// executes query and calls getResults() once promise is resolved
// promiseRejected() is called if the promise is rejected
qTask.execute(params).then(getResults).catch(promiseRejected);
}
// Called each time the promise is resolved
function getResults(response) {
// Loop through each results and assign a symbol and PopupTemplate
var basinResults = response.features.map(function (feature) {
// Sets the symbol of each resulting feature
feature.symbol = {
type: "simple-fill",
color: [212, 161, 87, 0.25]
};
feature.popupTemplate = popupTemplate;
return feature;
});
resultsLayer.addMany(basinResults);
// print the number of results returned to the user
document.getElementById("printResults").innerHTML =
basinResults.length + " results found!";
}
// Called each time the promise is rejected
function promiseRejected(error) {
console.error("Promise rejected: ", error.message);
}
});
</script>
</head>
<body>
<div id="mainViewDiv"></div>
<div id="optionsDiv">
<h2>Example</h2>
<div id="drop-downs">
<b>Basin</b>
<br/>
<select id="MajBas" class="widget"></select>
</div>
<br/>
<br/>
<button id="doBtn">Search</button> <br />
<p><span id="printResults"></span></p>
</div>
</body>
</html>
"MajBasin" is the name of the field in the attribute table containing the basin names that are visible in the drop down.