Query a FeatureLayer

1908
2
Jump to solution
10-11-2018 11:47 AM
JaredPilbeam2
MVP Regular Contributor

How do I query a feature layer? My feature layer is about 150 points with attributes. I'd like to be able to have the user query these points by "Type".  

I've had a look at this example: https://developers.arcgis.com/javascript/latest/sample-code/featurelayer-query/index.html As far as I can see I should be able to use it.

Based on the example, here's what I came up with using my own data. But it's not functioning.

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
    <title>Query features from a FeatureLayer - 4.9</title>

    <link rel="stylesheet" href="https://js.arcgis.com/4.9/esri/css/main.css">
    <script src="https://js.arcgis.com/4.9/"></script>

    <style>
        html,
        body,
        #viewDiv {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
        }

        #infoDiv {
            background-color: white;
            color: black;
            padding: 6px;
            width: 400px;
        }

        #results {
            font-weight: bolder;
        }
    </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 attTypeSelect = document.getElementById("attractions");

                //attractions
                var attractions = new FeatureLayer({
                    url: "https://services.arcgis.com/fGsbyIOAuxHnF97m/arcgis/rest/services/Attractions/FeatureServer/0?token=...",
                    outFields: ["*"],
                    id: "attractions",
                    visible: false
                });
                //GraphicsLayer for desplaying results
                var resultsLayer = new GraphicsLayer();

                var map = new Map({
                    basemap: "dark-gray",
                    layer: "attractions"
                });

                var view = new MapView({
                    container: "viewDiv",
                    map: map,
                    center: [-87.75188, 41.23308],
                    zoom: 10
                });
                view.ui.add("infoDiv", "top-right");

                //query all features from the attractions layer
                view.when(function () {
                    return attractions.when(function () {
                        var query = attractions.createQuery();
                        return attractions.queryFeatures(query);
                    });
                })
                    .then(getValues)
                    .then(getUniqueValues)
                    .then(addToSelect);

                // return an array of all the values in the
                // Type field of the attractions layer
                function getValues(response) {
                    var features = response.features;
                    var values = features.map(function (feature) {
                        return feature.attributes.Type;
                    });
                    return values;
                }

                // return an array of unique values in
                // the Type field of the attractions 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 attractions type
                // select element. This will allow the user
                // to filter attractions by type.
                function addToSelect(values) {
                    values.sort();
                    values.forEach(function (value) {
                        var option = document.createElement("option");
                        option.text = value;
                        attTypeSelect.add(option);
                    });

                    return setattractionsDefinitionExpression(attTypeSelect.value);
                }

                // set the definition expression on the attractions
                // layer to reflect the selection of the user
                function setattractionsDefinitionExpression(newValue) {
                    attractions.definitionExpression = "Type" + newValue + "'";

                    if (!attractions.visible) {
                        attractions.visible = true;
                    }

                    return queryForAtractionGeometries();
                }

                // Get all the geometries of the attractions layer
                // the createQuery() method creates a query
                // object that respects the definitionExpression
                // of the layer
                function queryForAttractionGeometries() {
                    var attractionsQuery = attractions.createQuery();

                    return attractions.queryFeatures(attractionsQuery)
                        .then(function (response) {
                            attractionsGeometries = response.features.map(function (feature) {
                                return feature.geometry;
                            });

                            return attractionsGeometries;
                        });
                }
            });

    </script>

</head>

<body>
    <div id="viewDiv"></div>
    <div id="infoDiv">
        Select attractions type:
        <select id="attractions"></select>
    </div>
</body>

</html>‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
Tags (3)
0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Esteemed Contributor

Jared,

  Here is your code fixed with comments on the changes needed:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
    <title>Query features from a FeatureLayer - 4.9</title>

    <link rel="stylesheet" href="https://js.arcgis.com/4.9/esri/css/main.css">
    <script src="https://js.arcgis.com/4.9/"></script>

    <style>
        html,
        body,
        #viewDiv {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
        }

        #infoDiv {
            background-color: white;
            color: black;
            padding: 6px;
            width: 400px;
        }

        #results {
            font-weight: bolder;
        }
    </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 attTypeSelect = document.getElementById("attractions");

                //attractions
                var attractions = new FeatureLayer({
                    url: "https://services.arcgis.com/fGsbyIOAuxHnF97m/arcgis/rest/services/Attractions/FeatureServer/0",
                    outFields: ["*"],
                    visible: false
                });

                //GraphicsLayer for desplaying results
                var resultsLayer = new GraphicsLayer();

                var map = new Map({
                    basemap: "dark-gray",
//You were passing a string "attractions" to a property called layer (which does not exist)
                    layers: [attractions]
                });

                var view = new MapView({
                    container: "viewDiv",
                    map: map,
                    center: [-87.75188, 41.23308],
                    zoom: 10
                });
                view.ui.add("infoDiv", "top-right");

                //query all features from the attractions layer
                view.when(function () {
                    return attractions.when(function () {
                        var query = attractions.createQuery();
                        return attractions.queryFeatures(query);
                    });
                })
                .then(getValues)
                .then(getUniqueValues)
                .then(addToSelect);

                // return an array of all the values in the
                // Type field of the attractions layer
                function getValues(response) {
                    var features = response.features;
                    var values = features.map(function (feature) {
                        return feature.attributes.Type;
                    });
                    return values;
                }

                // return an array of unique values in
                // the Type field of the attractions 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 attractions type
                // select element. This will allow the user
                // to filter attractions by type.
                function addToSelect(values) {
                    values.sort();
                    values.forEach(function (value) {
                        var option = document.createElement("option");
                        option.text = value;
                        attTypeSelect.add(option);
                    });

                    return setattractionsDefinitionExpression(attTypeSelect.value);
                }

                // set the definition expression on the attractions
                // layer to reflect the selection of the user
                function setattractionsDefinitionExpression(newValue) {
//You messed up the SQL syntax for the defenition query                  
                    attractions.definitionExpression = "Type = '" + newValue + "'";
                    if (!attractions.visible) {
                        attractions.visible = true;
                    }
//You misspelled the function name here                    
                    return queryForAttractionGeometries();
                }

//You forgot to add the evenet listener for attTypeSelect change
                // set a new definitionExpression on the attractions layer
                attTypeSelect.addEventListener("change", function () {
                  var type = event.target.value;
                  setattractionsDefinitionExpression(type);
                });

                // Get all the geometries of the attractions layer
                // the createQuery() method creates a query
                // object that respects the definitionExpression
                // of the layer
                function queryForAttractionGeometries() {
                    var attractionsQuery = attractions.createQuery();
                    return attractions.queryFeatures(attractionsQuery)
                        .then(function (response) {
                            attractionsGeometries = response.features.map(function (feature) {
                                return feature.geometry;
                            });
                            return attractionsGeometries;
                        });
                }
            });

    </script>

</head>

<body>
    <div id="viewDiv"></div>
    <div id="infoDiv">
        Select attractions type:
        <select id="attractions"></select>
    </div>
</body>

</html>

View solution in original post

0 Kudos
2 Replies
RobertScheitlin__GISP
MVP Esteemed Contributor

Jared,

  Here is your code fixed with comments on the changes needed:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
    <title>Query features from a FeatureLayer - 4.9</title>

    <link rel="stylesheet" href="https://js.arcgis.com/4.9/esri/css/main.css">
    <script src="https://js.arcgis.com/4.9/"></script>

    <style>
        html,
        body,
        #viewDiv {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
        }

        #infoDiv {
            background-color: white;
            color: black;
            padding: 6px;
            width: 400px;
        }

        #results {
            font-weight: bolder;
        }
    </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 attTypeSelect = document.getElementById("attractions");

                //attractions
                var attractions = new FeatureLayer({
                    url: "https://services.arcgis.com/fGsbyIOAuxHnF97m/arcgis/rest/services/Attractions/FeatureServer/0",
                    outFields: ["*"],
                    visible: false
                });

                //GraphicsLayer for desplaying results
                var resultsLayer = new GraphicsLayer();

                var map = new Map({
                    basemap: "dark-gray",
//You were passing a string "attractions" to a property called layer (which does not exist)
                    layers: [attractions]
                });

                var view = new MapView({
                    container: "viewDiv",
                    map: map,
                    center: [-87.75188, 41.23308],
                    zoom: 10
                });
                view.ui.add("infoDiv", "top-right");

                //query all features from the attractions layer
                view.when(function () {
                    return attractions.when(function () {
                        var query = attractions.createQuery();
                        return attractions.queryFeatures(query);
                    });
                })
                .then(getValues)
                .then(getUniqueValues)
                .then(addToSelect);

                // return an array of all the values in the
                // Type field of the attractions layer
                function getValues(response) {
                    var features = response.features;
                    var values = features.map(function (feature) {
                        return feature.attributes.Type;
                    });
                    return values;
                }

                // return an array of unique values in
                // the Type field of the attractions 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 attractions type
                // select element. This will allow the user
                // to filter attractions by type.
                function addToSelect(values) {
                    values.sort();
                    values.forEach(function (value) {
                        var option = document.createElement("option");
                        option.text = value;
                        attTypeSelect.add(option);
                    });

                    return setattractionsDefinitionExpression(attTypeSelect.value);
                }

                // set the definition expression on the attractions
                // layer to reflect the selection of the user
                function setattractionsDefinitionExpression(newValue) {
//You messed up the SQL syntax for the defenition query                  
                    attractions.definitionExpression = "Type = '" + newValue + "'";
                    if (!attractions.visible) {
                        attractions.visible = true;
                    }
//You misspelled the function name here                    
                    return queryForAttractionGeometries();
                }

//You forgot to add the evenet listener for attTypeSelect change
                // set a new definitionExpression on the attractions layer
                attTypeSelect.addEventListener("change", function () {
                  var type = event.target.value;
                  setattractionsDefinitionExpression(type);
                });

                // Get all the geometries of the attractions layer
                // the createQuery() method creates a query
                // object that respects the definitionExpression
                // of the layer
                function queryForAttractionGeometries() {
                    var attractionsQuery = attractions.createQuery();
                    return attractions.queryFeatures(attractionsQuery)
                        .then(function (response) {
                            attractionsGeometries = response.features.map(function (feature) {
                                return feature.geometry;
                            });
                            return attractionsGeometries;
                        });
                }
            });

    </script>

</head>

<body>
    <div id="viewDiv"></div>
    <div id="infoDiv">
        Select attractions type:
        <select id="attractions"></select>
    </div>
</body>

</html>
0 Kudos
JohnGrayson
Esri Regular Contributor

I'm not 100% sure, but it looks like the definitionExpression is not quite correct.  You can verify the query string by looking at the request being sent to the service in the browser dev tools, and then you can test it out in the service REST page.

attractions.definitionExpression = "Type = '" + newValue + "'";
0 Kudos