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.

    <meta charset="utf-8" />

    <title>Project viewer</title>

      #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 */

    <script src="https://js.arcgis.com/4.15/"></script>

        ], function(
         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
          .when(function () {
            return basinLayer.when(function () {
              var query = basinLayer.createQuery();
              return basinLayer.queryFeatures(query);
              document.getElementById("doBtn").addEventListener("click", 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 !== ""
            ) {
          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.forEach(function (value) {
            var option = document.createElement("option");
            option.text = value;
        //** 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
          // 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

        // 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;


          // 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);

    <div id="mainViewDiv"></div>
    <div id="optionsDiv">
        <div id="drop-downs">
        <select id="MajBas" class="widget"></select>
      <button id="doBtn">Search</button> <br />
      <p><span id="printResults"></span></p>

"MajBasin" is the name of the field in the attribute table containing the basin names that are visible in the drop down.

2 Answers 2


When setting params.where, the field name before the attribute value was missing. Thus, the updated code that builds a working query is:

params.where =
            "MajBas =" + "'" + basinTypeSelect.value + "'";

I populated the dropdowns by reading a json file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.