problems with featureLayer tied to dGrid example

1287
7
07-03-2012 12:33 PM
TracySchloss
Frequent Contributor
I'm trying to work through the sample http://help.arcgis.com/en/webapi/javascript/arcgis/demos/fl/fl_dgrid.html  that ties a feature layer to the new dgrid.  It works fine for me with polygons, but I can't seem to get this to work with points. The featurelayer draws fine.  The grid populates just fine.  In the selectGrid function when I debug, the row variable has a null for both its data and its element.  It does have an ID number which looks to be OBJECTID.

In the grid, where are row.data and row.element coming from?  I assume somehow assigned in the populateGrid function?
Here's my populateGrid:
  
 function populateGrid() {
      var qt = new esri.tasks.QueryTask(window.statesUrl);
      var query = new esri.tasks.Query();
      query.where = "1=1";
      query.returnGeometry = false;
      query.outFields = window.outFields;
      qt.execute(query, function(results) {
        var data = dojo.map(results.features, function(feature) {
          return {
            "featureId": feature.attributes[window.outFields[0]],
            "facility": feature.attributes[window.outFields[1]],
            "address": feature.attributes[window.outFields[2]],
            "city": feature.attributes[window.outFields[3]],
            "state": feature.attributes[window.outFields[4]]
          }
        });
        window.grid.renderArray(data);
        window.grid.sort('facility');
        
      });
    }


Here's my selectGrid function:

function selectGrid(e) {
      console.log("fl click: ", e.graphic.attributes.OBJECTID);
      var id = e.graphic.attributes.OBJECTID;
      var query = new esri.tasks.Query();
      query.objectIds = [e.graphic.attributes.OBJECTID];
      var states = map.getLayer("points");
      states.selectFeatures(query, esri.layers.FeatureLayer.SELECTION_NEW);
      grid.clearSelection();
      // dojo.forEach(states.graphics, function(g) {
      for ( var i = 0; i < states.graphics.length; i++ ) {
        var g = states.graphics;
        var row = grid.row(g.attributes.OBJECTID);
        // console.log("row is: ", row, row.data.featureId);
        if ( row && row.data && row.data.featureId == id ) {
          // grid.select(row);
          selectRow(row.element);
          row.element.scrollIntoView();
          break;
        }
      };
    }


When I put a breakpoint on the row variable, Firebug shows this as data undefined and element as null.  So the selectRow function that follows errors out.
When examing the query variable, I see it has a spatialRelationship of esriSpatialRelIntersects.  Is that where the problem is?  Do I need to define something different for the query since it's not a polygon?  I've not used a query.ObjectIds before.

My featureLayer does show that I have some selected features so I figure it's finding something, but maybe it's really not?
0 Kudos
7 Replies
KellyHutchins
Esri Frequent Contributor
There are a few changes you'll need to make to the sample in order for it to work with point features - beyond changing the column names and the layer url.

1. At ~ line 69 you'll want to modify the code to set a marker symbol instead of a fill symbol as the selection symbol.
fl.setSelectionSymbol(new esri.symbol.SimpleMarkerSymbol().setColor('#F9D89A'));

2. In the selectState function I had to change the line that gets the objectids to read the target's textContent instead of innerHTML:
 query.objectIds = [parseInt(e.target.textContent)]; 

3. In the selectState function I modified the code that centers the map on the selected feature. The original sample gets the selected polygons extent and uses getCenter to find the center point of that extent. With point features you don't have an extent but you do have the point so you don't need the extra step of getting the extent first so switch to the following:
window.map.centerAt(result[0].geometry);


Here's a fiddle that shows the sample working with point features:
http://jsfiddle.net/43KdU/
0 Kudos
TracySchloss
Frequent Contributor
I had the symbol changed and I would have gotten to the polygon vs point issue with the geometry.   The place I was getting stuck was the line for query.objectIds.

I changed what I saw as a problem in your selectState function, to define fl as getLayer("blockpoints").  This was originally the featureLayer with the ID of states, which doesn't exist is this modified version.

All these changes do let me select a grid row and highlight on the map.  It still doesn't work the other way, I can't select a point and have the row highlight in the grid.   When I look at the value for the row variable defined in var row = grid.row(g.attributes.OBJECTID), it doesn't look to contain all the information needed to correctly select the row.    There is a row returned, but its data says undefined and its element is null. This means it doesn't get past the if statement if ( row && row.data && row.data.featureId == id ) {

I don't see that it's working in your example either.
0 Kudos
KellyHutchins
Esri Frequent Contributor
I think part of the issue is that the points layer used in the test page I sent has lots of data. When we add this layer to the map we render it in OnDemand mode which means it will render the points in the current extent (and a bit more) and as you pan and zoom it will draw additional points. However when the data is added to the grid a query is done to get all the rows (using 1=1) but by default this only returns 1000 records and those 1000 records may not be the points currently displayed. So not all the points on the map are drawn in the grid we only see data for 1000 points.

What does your data that you are trying to work with look like - how many features? If there are only a few hundred you can try adding the feature layer in SNAPSHOT mode instead of ONDEMAND mode and see if that resolves the issue.



I had the symbol changed and I would have gotten to the polygon vs point issue with the geometry.   The place I was getting stuck was the line for query.objectIds.

I changed what I saw as a problem in your selectState function, to define fl as getLayer("blockpoints").  This was originally the featureLayer with the ID of states, which doesn't exist is this modified version.

All these changes do let me select a grid row and highlight on the map.  It still doesn't work the other way, I can't select a point and have the row highlight in the grid.   When I look at the value for the row variable defined in var row = grid.row(g.attributes.OBJECTID), it doesn't look to contain all the information needed to correctly select the row.    There is a row returned, but its data says undefined and its element is null. This means it doesn't get past the if statement if ( row && row.data && row.data.featureId == id ) {

I don't see that it's working in your example either.
0 Kudos
TracySchloss
Frequent Contributor
Most of my projects have well under 1000 points.  Switching to SNAPSHOT seems to have taken care of clicking on the grid to find the point.  I didn't like the map just centering , since I'm dealing with the whole state.  Instead I'm using centerAndZoom.

Clicking on the point and highlighting the record still isn't working though.  Like before, the row variable still as data undefined and element null.  The dgrid reference is still pretty sparse.
0 Kudos
TracySchloss
Frequent Contributor
I don't know if it is the fact I have a featureLayer or not.   I was off a couple of days.  When I opened this code up again today, it started working.  Then it stopped.  Now it sometimes highlights a row and sometimes not?!  Maybe it's having a hard time keeping up? 

It continues to work with clicking a row to highlight the feature, but not the other way.
0 Kudos
DavidJenkins
New Contributor III
I am having the "exact" same issue.

JS API 3.2 / Dojo 1.7

.NET Framework 4.0 - I mention this because I have recently come across information in a non-GIS forum while performing an online search on the error keywords.  I found that this behavior MAY be an issue with dgrid not working correctly with .NET 4.0.  I have not rolled it back so I cannot confirm.  I am hesitant to do so because I'm not positive of the implications.  However, I can confirm that it is not browser related.

Another quirk is that dgrid populates empty rows for supressed records when using bufferRows: Infinity.

The error / problem persists whether or not you change the query.objectIds to textContent.  Even in your code Kelly.  If I copy your sample to my dev environment (Aptana) then I can reproduce the same problem with your code too.

As a WORKAROUND, I have found that I can circumvent the error if before I click on any point, I scroll through the records in dgrid and force them to become available.  Once I do that, I can click on any point without error because the row is not empty.  I can't seem to bring myself to post a message to users to do this...

Hope this helps because I need an answer too!

Thanks,

Dave Jenkins
0 Kudos
by Anonymous User
Not applicable
I am not 100% sure this will solve your issues but I have found some problems with the esri dgrid example when using more than 50 or 60 features. Hopefully this will help someone out there.

I am developing a crime app using the dgrid and a featurelayer. When the user clicks on a crime point in the map it is supposed to highlight the corresponding record in the dgrid. Sometimes it would work other time it wouldn't. Using Firebug I noticed that not all of my crime records were showing up in the dgrid. The data was in the dgrid store they just were not being shown. After some searching I realized it was probably being caused by the bug listed in item #1.

1. There is know bug with the dgrid widget that has caused me serious pain while developing my app. It sounds like it is effecting you guys as well.
     https://github.com/SitePen/dgrid/issues/318

After banging my head against the wall for 3 straight days I finally figured out a work around. Rather than using a store I simply rendered the data array.

 function onSelectionResults(fs) {            
           var data = dojo.map(fs, function (feature) {
                return {
                    // property names used here match those used when creating the dgrid
                    'id': feature.attributes[window.outFields[2]],
                    "INC_REPORT": feature.attributes[window.outFields[0]],
                    "AGENCY_CODE": feature.attributes[window.outFields[3]],
                    "DESCRIPTION": feature.attributes[window.outFields[4]],
                    "START_DATE": feature.attributes[window.outFields[5]],
                    "ADDRESS": feature.attributes[window.outFields[6]]
                }
            });
        
          /*--------these two lines went away-----------*/
            //var mStore = new dojo.store.Memory({data:data})
           // window.grid.set("store", mStore);
         /*-----------------------------------------------*/
        
       /*------THIS IS WHAT I USE NOW---------/
            window.grid.renderArray(data)
     /*---------------------------------------*/


Then I had to figure out how to select a row from a grid without a store.
      

// fires when a feature on the map is clicked        
      function selectGrid(e) {
         var id = e.graphic.attributes.OBJECTID;

       /*rowNode holds  all the dom Nodes that reference the objectid of the clicked crime point*/
       /*the dojo.query returned a 9 object array. Using firebug I found the array index that corresponded to the row node*/
         var rowNode = dojo.query("*", dojo.byId('div')).filter(function (node) { if
        (node.textContent.indexOf(id) !== -1) { return node; } });

         
        //index[6] is where the row is returned from the query
            var rowIdx = window.grid.row(rowNode[6].rowIndex);
            if (rowIdx.data != undefined) 
            {
                window.grid.clearSelection();
                window.grid.select(rowIdx);
                grid.bodyNode.scrollTop = rowIdx.element.offsetTop;
            }
            else
            {
            var pte = pointToExtent(map, e.mapPoint, 15)
            //  console.log('the featurelayer click extent xmax', pte.xmax)
            //  console.log('the featurelayer click extent ymax', pte.ymax)
             findPointsInExtent(pte, e)
            }
        }


I have tested the code with 500 records and so far its stable.
0 Kudos