Select to view content in your preferred language

Is there any way to get a count of the number of features in a FeatureLayer?

10595
27
12-19-2016 06:19 AM
JohnAdams
Occasional Contributor

I have a FeatureLayer map service from which I would like to get a count of the number of features. I would have thought such a thing would be a basic kind of functionality, but looking through the Javascript API for FeatureLayer, I can find nothing that looks like it does that. Unless I'm missing something?

What I would like to do is something like this:

var myLayer = new FeatureLayer("service url here with maybe a filter");

var count = myLayer.count;

Seems to be a basic thing to have - right? I guess not?

Tags (2)
27 Replies
JohnAdams
Occasional Contributor

Almost forgot ... I realize I have double-inner function calls and thus need to do a double-return, so I've also tried something like this:

var query = new Query();
query.where = "Zip = '" + SelectedZip + "'";

var num;
num = featLayer.queryCount(query, num = function(count) {
return count;
} return count;);

And variations thereof. But I can't do the "num = function(count)" without getting a syntax error.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

John,

   Here is a sample of how I recommended to get the count using the FeatureLayer graphics length:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>FeatureLayer</title>

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

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

<script>
require([
    "esri/map",
    "esri/layers/FeatureLayer",
    "dojo/on",
    "dojo/domReady!"
  ],
  function(
    Map,
    FeatureLayer,
    on
  ) {

    var map = new Map("map", {
      basemap: "hybrid",
      center: [-82.44109, 35.6122],
      zoom: 17
    });

    // Carbon storage of trees in Warren Wilson College.
    var featureLayer = new FeatureLayer("https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Landscape_Trees/FeatureServer/0", {
      "outFields": ["*"]
    });
    featureLayer.setDefinitionExpression("Tree_Age > 5");
    map.addLayer(featureLayer);
    on.once(featureLayer, "update-end", function() {
      console.info(featureLayer.graphics.length);
    })
  });
</script>
</head>

<body>
  <div id="map"></div>
</body>

</html>

And here is a sample for doing it using the query from a function:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>FeatureLayer</title>

<link rel="stylesheet" href="https://js.arcgis.com/3.18/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.18/esri/css/esri.css">
<script src="https://js.arcgis.com/3.18/"></script>

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

<script>
var featCnt;
require([
    "esri/map",
    "esri/layers/FeatureLayer",
    "dojo/on",
    "esri/tasks/query",
    "dojo/parser",
    "dojo/dom",
    "dojo/Deferred",
    "dijit/form/Button",
    "dojo/domReady!"
  ],
  function(
    Map,
    FeatureLayer,
    on,
    Query,
    parser,
    dom,
    Deferred
  ) {
    parser.parse();
    var map = new Map("map", {
      basemap: "hybrid",
      center: [-82.44109, 35.6122],
      zoom: 17
    });

    // Carbon storage of trees in Warren Wilson College.
    var featureLayer = new FeatureLayer("https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Landscape_Trees/FeatureServer/0", {
      "outFields": ["*"]
    });
    featureLayer.setDefinitionExpression("Tree_Age > 5");
    map.addLayer(featureLayer);
    // on.once(featureLayer, "update-end", function() {
    //   console.info(featureLayer.graphics.length);
    // })

    on(dijit.byId("cntBtn"), "click", function(){
      getFeatureCnt().then(function(evt){
        alert(evt);
      })
    },this);

    function getFeatureCnt(){
      var query = new Query();
      query.where = featureLayer.getDefinitionExpression();
      var def = new Deferred();
      featureLayer.queryCount(query, function(count) {
        def.resolve(count);
      });
      return def;
    }
  });
</script>
</head>

<body class="claro">
  <div id="map">
    <button data-dojo-type="dijit/form/Button" type="button" id="cntBtn">Get Count</button>
  </div>
</body>

</html>
RobertScheitlin__GISP
MVP Emeritus

Or using a global var:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>FeatureLayer</title>

<link rel="stylesheet" href="https://js.arcgis.com/3.18/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.18/esri/css/esri.css">
<script src="https://js.arcgis.com/3.18/"></script>

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

<script>
var featCnt;
require([
    "esri/map",
    "esri/layers/FeatureLayer",
    "dojo/on",
    "esri/tasks/query",
    "dojo/parser",
    "dijit/form/Button",
    "dojo/domReady!"
  ],
  function(
    Map,
    FeatureLayer,
    on,
    Query,
    parser
  ) {
    parser.parse();
    var map = new Map("map", {
      basemap: "hybrid",
      center: [-82.44109, 35.6122],
      zoom: 17
    });

    // Carbon storage of trees in Warren Wilson College.
    var featureLayer = new FeatureLayer("https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Landscape_Trees/FeatureServer/0", {
      "outFields": ["*"]
    });
    featureLayer.setDefinitionExpression("Tree_Age > 5");
    map.addLayer(featureLayer);
    getFeatureCnt();

    on(dijit.byId("cntBtn"), "click", function(){
      alert(featCnt);
    },this);

    function getFeatureCnt(){
      var query = new Query();
      query.where = featureLayer.getDefinitionExpression();
      featureLayer.queryCount(query, function(count) {
        featCnt = count;
      });
    }
  });
</script>
</head>

<body class="claro">
  <div id="map">
    <button data-dojo-type="dijit/form/Button" type="button" id="cntBtn">Get Count</button>
  </div>
</body>

</html>
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
JohnAdams
Occasional Contributor

Your examples aren't working. I think you have a problem with the feature layers (they don't seem to be loading at all).

My attempts to use a global variable are essentially the same you have above. I declare the variable in the same spot you do, and assign it in basically the same queryCount function you have, but whenever I try to access it *outside* the queryCount function, it returns as undefined.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

John,

  I am not sure what going wrong on your end as all three of those samples work fine for me. Can you access the url that is in the samples just from you browser address bar?

0 Kudos
JohnAdams
Occasional Contributor

The first two are working now, but that's not what I want to do. Just the last one with the global variable still doesn't work - which unfortunately is what I want to do. The button loads but then it just hangs there. I need to have several variables which I need to access outside of the queryCount function, and even outside of the button handler. The variables would be created via the queryCount function, so basically I need that function to return a value. Every time I assign my global variables inside the queryCount function, the value disappears once you get outside the function (again, even though they're declared globally).

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

John,

   As I said strange. I just tested my last posted sample again and beside missing a comma after "dojo/parser". It work fine for me still. When I click the button I get an alert with 2 as the result.

0 Kudos
JohnAdams
Occasional Contributor

Didn't notice the missing comma. Works now. I'll let you know if I can figure out how to get this into my code.

0 Kudos
JohnAdams
Occasional Contributor

I've narrowed down the issue. According to your code I should be doing this:

----------------------------------------

getFeatureCnt();

on(dijit.byId("cntBtn"), "click", function(){
alert(featCnt); // this gets saved globally
},this);

function getFeatureCnt()
{
var query = new Query();
query.where = "Zip = '64108'";
featureLayer.queryCount(query, function(count) {
featCnt = count;
});
}

--------------------------------------

However, I *need* to call the getFeatureCnt function from within the button handler, like this:

--------------------------------------

on(dijit.byId("cntBtn"), "click", function(){
getFeatureCnt();
alert(featCnt); // this does not get saved globally
},this);

function getFeatureCnt()
{
var query = new Query();
query.where = "Zip = '64108'";
featureLayer.queryCount(query, function(count) {
featCnt = count;
});
}

----------------------------

Once you arrange it like that, you notice it does not save featCnt globally and you get an "undefined" error message, which is what 's been happening to me. The reason I need to arrange it that way is because I need to do an if-else decision depending on what another variable is, and depending on the answer, pass in a certain value into those functions. Sort of like this:

on(dijit.byId("cntBtn"), "click", function(){
if (x=="one") getFeatureCnt(1);

else if (x=="two") getFeatureCnt(2);

else getFeatureCnt(3);
alert(featCnt); // this does not get saved globally
},this);

So I'm gonna have to figure out something else.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

John,

   It is not the fact that the code is not working but you are not understanding the asynchronous nature of the query that is being called. JS code is not syncoronus like other languages, it does not wait for a function to complete before running the next line so when you do:

on(dijit.byId("cntBtn"), "click", function(){
getFeatureCnt();
alert(featCnt); // this does not get saved globally
},this);

The alert is called before the getFeatureCnt has returned from the server and thus your alert of featCnt is undefined. If you are going to force the code to wait for the query return then you have to use a deferred like I did in the second sample I posted.

0 Kudos