How do I set up autocomplete on a query? My app is already set up to query a feature layer. I'd just like to know how to incorporate an autocomplete on the feature layer query so that the feature's attributes from the Category field will be listed as the user types.
These help docs are similar, but I don't need another text box:
-Auto complete a textbox from a map service in a widget
<script>
// JavaScript source code
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/FeatureLayer",
"esri/layers/GraphicsLayer",
"esri/widgets/Home",
], function (
Map,
MapView,
FeatureLayer,
GraphicsLayer,
Home
) {
var catTypeSelect = document.getElementById("category");
var keyTypeSelect = document.getElementById("keyword");
var filterButton = document.getElementById("filterBtn");
var resRb = document.getElementById("ResidentialRB");
// Recycle
var recycleLayer = new FeatureLayer({
portalItem: {
// autocasts as new PortalItem()
id: "b5665da3feab4b6091914cbfe4ab028f"
},
});
// GraphicsLayer for displaying results
var resultsLayer = new GraphicsLayer();
//Set map view
var map = new Map({
basemap: "dark-gray",
layers: [recycleLayer, resultsLayer]
});
var view = new MapView({
container: "viewDiv",
map: map,
center: [-87.95, 41.47],
zoom: 9
});
// query all features from the recycle layer
view
.when(function () {
return recycleLayer.when(function () {
var query = recycleLayer.createQuery();
return recycleLayer.queryFeatures(query);
});
})
.then(getValues)
.then(getUniqueValues)
.then(addToSelect)
// re-query the layer based on the selected Category and re-populate the keyword select
catTypeSelect.addEventListener("change", function () {
var sqlExp = "";
if (catTypeSelect.selectedIndex > 0) {
sqlExp += "Category LIKE '%" + catTypeSelect.options[catTypeSelect.selectedIndex].value + "%'";
}
var query = recycleLayer.createQuery();
query.where = sqlExp;
recycleLayer.queryFeatures(query)
.then(getValues2)
.then(getUniqueValues2)
.then(addToSelect2)
});
// return an array of all the values in the
// Category and item_keyword fields of the Recycle layer
function getValues(response) {
var features = response.features;
var values = features.map(function (feature) {
return {
Category: feature.attributes.Category,
item_keyword: feature.attributes.item_keyword
}
});
return values;
}
// re-query the layer based on the selected Category and re-populate the keyword select
function getValues2(response) {
var features = response.features;
var values = features.map(function (feature) {
return feature.attributes.item_keyword
});
return values;
}
// return an array of unique values in
// the item_keyword and Category fields of the Recycle layer
function getUniqueValues(values) {
var uniqueKeyValues = [];
var uniqueCatValues = [];
values.forEach(function (item, i) {
var keyVal = item.item_keyword.split(";");
var catVal = item.Category.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
};
}
// re-query the layer based on the selected Category and re-populate the keyword select
function getUniqueValues2(values) {
var uniqueKeyValues = [];
values.forEach(function (item, i) {
var keyVal = item.split(";");
keyVal.map(function (val2) {
if (
(uniqueKeyValues.length < 1 || uniqueKeyValues.indexOf(val2) === -1) &&
val2 !== ""
) {
uniqueKeyValues.push(val2);
}
});
});
return uniqueKeyValues;
}
// Add the unique values to the recycle type
// select element. This will allow the user
// to filter categories by type.
function addToSelect(values) {
var dOpt = document.createElement("option");
dOpt.value = "";
dOpt.selected = true;
dOpt.text = "Select one";
catTypeSelect.add(dOpt);
values.uCatVals.sort();
values.uCatVals.forEach(function (value) {
var option = document.createElement("option");
option.text = value;
catTypeSelect.add(option);
});
var dOpt2 = document.createElement("option");
dOpt2.value = "";
dOpt2.selected = true;
dOpt2.text = "Select one";
keyTypeSelect.add(dOpt2);
values.uKeyVals.sort();
values.uKeyVals.forEach(function (value) {
var option = document.createElement("option");
option.text = value;
keyTypeSelect.add(option);
});
return setDefinitionExpression();
}
// re-query the layer based on the selected Category and re-populate the keyword select
function addToSelect2(values) {
while (keyTypeSelect.options.length > 0) {
keyTypeSelect.remove(0);
}
var dOpt2 = document.createElement("option");
dOpt2.value = "";
dOpt2.disabled = true;
dOpt2.selected = true;
dOpt2.text = "Select one";
keyTypeSelect.add(dOpt2);
values.sort();
values.forEach(function (value) {
var option = document.createElement("option");
option.text = value;
keyTypeSelect.add(option);
});
return true
}
// set the definition expression on the recycle
// layer to reflect the selection of the user
function setDefinitionExpression() {
var sqlExp = "";
if (catTypeSelect.selectedIndex > 0) {
sqlExp += "Category LIKE '%" + catTypeSelect.options[catTypeSelect.selectedIndex].value + "%'";
}
if (keyTypeSelect.selectedIndex > 0) {
if (sqlExp === "") {
sqlExp += "item_keyword LIKE '%" + keyTypeSelect.options[keyTypeSelect.selectedIndex].value + "%'";
} else {
sqlExp += " AND item_keyword LIKE '%" + keyTypeSelect.options[keyTypeSelect.selectedIndex].value + "%'";
}
}
if (resRb.checked) {
if (sqlExp !== "") {
sqlExp += " AND USER_IsRes = 'TRUE'";
}
} else {
if (sqlExp !== "") {
sqlExp += " AND USER_IsBus = 'TRUE'";
}
}
console.info(sqlExp);
recycleLayer.definitionExpression = sqlExp;
if (!recycleLayer.visible) {
recycleLayer.visible = true;
}
return queryForGeometries();
}
// Get all the geometries of the recycle layer
// the createQuery() method creates a query
// object that respects the definitionExpression
// of the layer
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();
});
});
</script>
Here's the whole app on Codepen.