dgrid not populated with Memory - querytask results

1905
16
Jump to solution
10-28-2013 06:19 AM
TracySchloss
Frequent Contributor
I have found multiple threads about populating a dgrid from results of a query task, but I still can't figure out what is wrong with the way I have my dGrid and Memory created. 

I have multiple queries getting executed, and each of the query results will be put in a separate Title Pane within a Floating Pane.  The title panes are getting created and I see that my Memory is populated, but I must not have this formatted correctly, because when I use it as the store for my dGrid, I get an empty grid.  The loop that reads the attribute names to create the columns look right.
function queryGeometryResultsHandler_toGrid(results, idx) { //format the data for the data grid var dataList = {};     dataList.data = arrayUtils.map(results.features, function(feature){              return feature.attributes;     });     var currentMemory = new Memory({data:dataList.data, idProperty:'OBJECTID'});      var gridcolumns = [];          for (attName in dataList.data[0]) {             if (attName != "Shape" && attName !== "Shape.area" && attName !== "Shape.len") {                 var objects = {};                 objects.label = attName;                 objects.field = attName;                 gridcolumns.push(objects);             }         }  //create a titlePane in the floatingPane for each visible layer     var currentLayerId = qTaskNameList[idx];//a list of layers created in query task functions     var paneTitle = (currentLayerId.split('_').join(' '))+"  ("+results.features.length+")";//formats string to look nice     tp = new TitlePane({ id: 'gridPane_'+currentLayerId, title: paneTitle, splitter:true, class:'reportTitlePane'});     registry.byId("reportContainer").addChild(tp);     tp.startup();  // Create Grid using structure and data defined above     grid = new Grid({id:currentLayerId+'_grid', autoHeight:true, columns:gridcolumns, store:currentMemory} ); //dgrid              grid.startup();            if (results.features.length > 0) {            tp.set("content", grid);         }else {             tp.set("content", "No features found");         }     }


I had this working in non-AMD style, but there I was using ItemFileReadStore and Dojox.Grid.DataGrid, so I know my theory is basically sound, just not the syntax.

Here's a link.  You have to turn on some layer other than legislative districts, like schools,  and then enter a district number to initiate the query.  https://ogitest.oa.mo.gov/LEGIS/LegislativeAnalysis/index.html
0 Kudos
1 Solution

Accepted Solutions
KenBuja
MVP Esteemed Contributor
I excluded the Shape field with the ColumnHider extension. Take a look at the buildColumns function in my code above which shows how the "hidden" property was added to the Shape field.

As for the TitlePane scrollbars, this post says to set overflow to auto. Also, take a look at this Fiddle that was put up in this post. You can modify the content to make the horizontal scroll bar appear.

View solution in original post

0 Kudos
16 Replies
KenBurcham
Occasional Contributor
In the eternal words of Vizzini, "I do not think attName means what you think it means."  🙂

Ok, sorry, it is a Tuesday...

At first glance, I think the attName you're getting back from iterating over that first row of attributes (dataList.data[0]) isn't a column name and that is throwing things off.

Hope that helps!

ken.
0 Kudos
TracySchloss
Frequent Contributor
Inconceivable!  I think I got that code from another forum post.  All I'm trying to do is create an array of column names.  I'm sure there's a lot of different ways I can go about it. Something I read in another thread suggested there was a problem with IE getting the information in an array and that's when I introduced the line
var objects = {}
instead. 

It looks like there are multiple ways to define columns.  I think I'm following the 3rd example on the Hello dgrid page
http://dojofoundation.org/packages/dgrid/tutorials/hello_dgrid/
0 Kudos
KenBurcham
Occasional Contributor
You might try a strategically placed "console.dir(attrName)" to see exactly what is coming back. 

https://developers.arcgis.com/en/javascript/jsapi/graphic-amd.html#attributes  indicates it is an object with a name/value pair, so you'll probably need to do something like: attrName.name in order to get the column name.

"...and no more rhyming now... I mean it!"

ken.
0 Kudos
TracySchloss
Frequent Contributor
attName is getting returned as a string with the field names I expect, first OBJECTID, then Facility, then Address etc.  If it's a column problem, then I'm getting lost in the right way to format it.  I was trying to follow the first style in the Hello dGrid example from that page's tutorial.  It looks like I can have columns defined as

1. As an array of objects with explicit field and label properties:

var columns = [
    {
        field: "first",
        label: "First Name"
    },
    {
        field: "last",
        label: "Last Name"
    },
    {
        field: "age",
        label: "Age"
    }
];


or
2. As a hash map, where the key is used as the "field" and the value is an object containing a "label" property:
 
var columns = {
    first: {
        label: "First Name"
    },
    last: {
        label: "Last Name"
    },
    age: {
        label: "Age"
    }
};

or
3. As a hash map, where the key is used as the "field" and the value is used as the "label":
var columns = {
    first: "First Name",
    last: "Last Name",
    age: "Age"
};


When it's done looping through to populate gridcolumns, it looks like this:
gridcolumns
 

[Object { label="OBJECTID", 
field="OBJECTID"
}, 
Object { label="CtyDist", 
field="CtyDist"
}, Object { label="Facility"
,  field="Facility"
},
Object { label="Address"
, field="Address"
}


This isn't quite perfect looking in this post because I copy/pasted from the Firebug console and it had a lot of extra space that I tried to edit out.  But you do see that my attribute names are getting returned.  Maybe the format of label:"myfieldName', field:"myfieldName", isn't the right format to follow after all?  Or maybe it doesn't like that it's an array of objects?
0 Kudos
TracySchloss
Frequent Contributor
I should also mention it doesn't completely dislike the columns variable, because the pane is populated with headers, there's just no data.  That's why I was focusing more on the Memory than the grid constructor.
0 Kudos
KenBuja
MVP Esteemed Contributor
Have you tried issuing startup on the titlepane after adding the dGrid to it? In my application, I add a dGrid to ContentPane, then start up the ContentPane. This will also start up the dGrid. I'm not using store, however, I'm using renderArray

    function populateTC(results, evt) {
        try {
            if (dijit.byId('tabs').hasChildren) {
                dijit.byId('tabs').destroyDescendants();
            }

            if (results.length === 0) {
                console.log('Nothing found.');
                return;
            }

            var combineResults = {};
            for (var i = 0, len = results.length; i < len; i++) {
                var result = results;
                var feature = result.feature;
                var lyrName = result.layerName.replace(' ', '');
                if (combineResults.hasOwnProperty(lyrName)) {
                    combineResults[lyrName].push(result);
                }
                else {
                    combineResults[lyrName] = [result];
                }
                switch (feature.geometry.type) {
                    case "point": case "multipoint":
                        layerResultsGraphic.add(new esri.Graphic(feature.geometry, symbolResultPoint, feature.attributes));
                        break;
                    case "polyline":
                        layerResultsGraphic.add(new esri.Graphic(feature.geometry, symbolResultPolyline, feature.attributes));
                        break;
                    case "polygon": case "extent":
                        layerResultsGraphic.add(new esri.Graphic(feature.geometry, symbolResultPolygon, feature.attributes));
                        break;
                }
            }

            for (result in combineResults) {
                if (combineResults.hasOwnProperty(result)) {

                    var columns = buildColumns(combineResults[result][0].feature);
                    var features = [];

                    for (i = 0, len = combineResults[result].length; i < len; i++) {
                        features.push(combineResults[result].feature);
                    }

                    var data = array.map(features, function (feature) {
                        return lang.clone(feature.attributes);
                    });

                    var dataGrid = new (declare([Grid, Selection, DijitRegistry, ColumnHider]))({
                        id: "dgrid_" + combineResults[result][0].layerId,
                        bufferRows: Infinity,
                        columns: columns,
                        selectionMode: "single",
                        "class": "resultsGrid"
                    });

                    var gridWidth = "width: " + String(columns.length * 100) + "px";
                    dataGrid.addCssRule("#" + dataGrid.id, gridWidth);

                    dataGrid.on(".dgrid-row:click", gridSelect);
                    dataGrid.on("show", function () {
                        dataGrid.resize();
                    });
                    dataGrid.on(mouseUtil.enterRow, gridEnter);
                    dataGrid.on(mouseUtil.leaveRow, function () {
                        map.graphics.clear();
                    });
                    var plural = "";
                    if (combineResults[result].length !== 1) { plural = "s"; }
                    var cp = new dijit.layout.ContentPane({
                        id: result,
                        content: "<strong>" + combineResults[result][0].layerName + "</strong> (" + combineResults[result].length + " feature" + plural + ")",
                        //content: dataGrid,
                        title: combineResults[result][0].layerId,
                        style: "overflow: auto"
                    }).placeAt(dijit.byId('tabs'));

                    cp.addChild(dataGrid);
                    cp.startup();

                    dataGrid.renderArray(data);
                }
            }
            tc.startup();
            tc.resize();
            map.infoWindow.show(evt.screenPoint, map.getInfoWindowAnchor(evt.screenPoint));
        }
        catch (e) { console.log(e.message); }
    }

    function buildColumns(feature) {
        var attributes = feature.attributes;
        var columns = [];

        for (var attribute in attributes) {
            if (attributes.hasOwnProperty(attribute)) {
                var objects = {};
                objects.label = attribute;
                objects.field = attribute;
                if (attribute === "Shape") {
                    objects.hidden = true;
                }
                columns.push(objects);
            }
        }
        return columns;
    }



Here's a production version of that. Turn on several layers and click on overlapping features to see it in play.

This also shows how to create dGrids of varying widths, so the columns are not squished down to fit the width of the TitlePane. I've assigned all columns a width of 100 pixels, then calculating the grid's width by multiplying the number of columns by 100. Then I add a CSS rule for that grid.

var gridWidth = "width: " + String(columns.length * 100) + "px";
dataGrid.addCssRule("#" + dataGrid.id, gridWidth);
0 Kudos
TracySchloss
Frequent Contributor
I had another thread where I was asking the differences between the different types of grids, what data they supported etc, but I got no replies.  From what I've read, dGrid supports rendererArray, but if I was using onDemandGrid etc, I could set the store parameter instead and it doesn't support rendererArray.

Just for fun, I changed grid to be an OnDemandGrid instead of dGrid, leaving my grid definition with the Memory the way I had it. Suddenly I had data!  But now there are no column headers ...
0 Kudos
TracySchloss
Frequent Contributor
I realized that I did have headers, but they weren't styled right.  I went back to the thread you helped me on earlier (I think it was you) that the 'headers were shoved out the top'. 

I have headers and data.  I'm down to styling.  I have a grid, inside a title pane inside a floating pane.  The grid's rarely going to fit, no matter how big I size the panes.  Obviously I need scrollbars.  Would those be a style on the title panes then?

I also have some columns I really don't want to appear, like Shape.len and Shape.area.  I'll need to figure out where to limit my columns and my data so neither are shown.
0 Kudos
KenBuja
MVP Esteemed Contributor
I excluded the Shape field with the ColumnHider extension. Take a look at the buildColumns function in my code above which shows how the "hidden" property was added to the Shape field.

As for the TitlePane scrollbars, this post says to set overflow to auto. Also, take a look at this Fiddle that was put up in this post. You can modify the content to make the horizontal scroll bar appear.
0 Kudos