Add Attachments to OnDemandGrid

110
7
Jump to solution
02-19-2020 12:35 PM
Highlighted
New Contributor III

I'm working with api 3.31. I have an app that loads an onDemandGrid via a datastore that is loaded by a querytask. It works fine, except that I need to get attachments that exist in the source data, and put the attachment into a column that is added in the createGrid function: queryAttachmentsInfo does not seem to be available via the QueryTask. So I wonder if anyone has dealt with this problem of getting attachments into a datagrid, and perhaps any suggestions as to how I could populate the attachments column in this application's grid.

Here is the code that creates the grid:

function createGrid() {
var egrid = declare([ Grid, Keyboard, Selection]);
this.gridlist = new egrid({
selectionMode: 'single',
columns: {
NAME: "Name",
LIFE_CYCLE_STATUS: "Status",
HIGH_SIDE_VOLTAGE: "High Side Voltage",
OWNERSHIP_CODE: "Ownership",
ADDRESS: "Address",
CITY: "City",
COUNTY: "County",
STATE: "State",
Attachments: { label: "Attachments", formatter: makeLink}
},
showHeader: true,
collection: this.store,
minRowsPerPage: 200,
queryOptions: {
sort: [{ attribute: "NAME" }]
},
store: new Memory({data: [], idProperty: "id"})
}, "grid");
this.gridlist.startup();

And this is where I create the store:

function loadSubstations () {
var queryTaskSubstations = new QueryTask(facilityLayer.url);
var query = new Query();
query.returnGeometry = true;
query.outFields=["OBJECTID","NAME","CODE","HIGH_SIDE_VOLTAGE","LIFE_CYCLE_STATUS","OWNERSHIP_CODE","ADDRESS","CITY","COUNTY","STATE"];
query.where = "1=1";
queryTaskSubstations.execute(query, lang.hitch(this, showResults));
function showResults (results) {
var resultFeatures = results.features;
var featureCount = results.features.length;
for (var i = 0; i < featureCount; i++){
var features = results.features;
esubs.push(features);
}
var subs = arrayUtils.map(esubs, function (feature) {
return {
"id": feature.attributes["OBJECTID"],
"NAME": feature.attributes["NAME"],
"LIFE_CYCLE_STATUS": feature.attributes["LIFE_CYCLE_STATUS"],
"HIGH_SIDE_VOLTAGE": feature.attributes["HIGH_SIDE_VOLTAGE"],
"OWNERSHIP_CODE": feature.attributes["OWNERSHIP_CODE"],
"ADDRESS": feature.attributes["ADDRESS"],
"CITY": feature.attributes["CITY"],
"COUNTY": feature.attributes["COUNTY"],
"STATE": feature.attributes["STATE"],
"shape": feature.geometry
};

});
subdataStore = new Memory({data:subs, idProperty:"id"});
this.gridlist.set("store", subdataStore);
this.gridlist.set("collection", subdataStore);
}
}

Thanks,

 Jim Faron

Reply
0 Kudos
1 Solution

Accepted Solutions
Highlighted
MVP Esteemed Contributor

James,

   As you iterate through your esubs array you are assigning the ObjectID to the grids id field.

"id": feature.attributes["OBJECTID"],

So you have the ObjectID right there that you can use in the your attachment query. the attachment query is async so you will have to populate the attachment field after the query is done by selecting the row using the grids select method and the ObjectId that matches the one returned from the async process.

View solution in original post

Reply
0 Kudos
7 Replies
Highlighted
MVP Esteemed Contributor

Jim,

   The ability to get attachments is not part of QueryTask. You have to use the FeatureLayer queryattachmentInfos method.

https://developers.arcgis.com/javascript/3/jsapi/featurelayer-amd.html#queryattachmentinfos 

Reply
0 Kudos
Highlighted
New Contributor III

Robert,

I did see that being used in on click functions for use in popups, but I haven't found a sample, or I'm not wrapping my head around how to iterate through the feature layer to get the oids without an event that triggers it such as click. I guess I could work with "on("load"....), but I don't see how to get to the actual data with that event.

Reply
0 Kudos
Highlighted
MVP Esteemed Contributor

James,

   As you iterate through your esubs array you are assigning the ObjectID to the grids id field.

"id": feature.attributes["OBJECTID"],

So you have the ObjectID right there that you can use in the your attachment query. the attachment query is async so you will have to populate the attachment field after the query is done by selecting the row using the grids select method and the ObjectId that matches the one returned from the async process.

View solution in original post

Reply
0 Kudos
Highlighted
MVP Esteemed Contributor

James,

   Have you considered how you will handle the fact that a OID can have more then one attachment?

Reply
0 Kudos
Highlighted
New Contributor III

Robert,

I see what you are referring to regarding the esubs array having the OID. I can loop through the features in the FeatureLayer with update-end event, and apply the queryAttachmentInfos method in the loop (this stumped me for a while, as I never had occasion to use that event).

For this project, I only have one attachment, but I guess if I had more than one I would have to create an additional field in the grid?

Thanks again for the help.

Jim Faron

Reply
0 Kudos
Highlighted
MVP Esteemed Contributor

Here is an snippit of how I go about this:

          window.grid = new (declare([Grid, Selection]))({
// use Infinity so that all data is available in the grid
bufferRows: Infinity,
columns: {
"id": "ID",
"PPIN": "PPIN",
"NAME": "Owners Name",
"Attachment": { label: "Attachment", formatter: makeLink }
},
loadingMessage: "Loading data...",
}, "grid");

...

map.on("load", function( evt ){
// show the border container now that the dijits
// are rendered and the map has loaded
domStyle.set(registry.byId("container").domNode, "visibility", "visible");
populateGrid(Memory); // pass a reference to the MemoryStore constructor
});

...

function populateGrid(Memory) {
var qt = new QueryTask(window.parcelUrl);
var query = new Query();
query.where = "1=1";
query.returnGeometry = false;
query.outFields = window.outFields;
qt.execute(query, function(results) {
window.resultsLen = results.features.length;
window.attRsltCnt = 0;
window.data = array.map(results.features, function(feature) {
//Get attachment infos
var oid = feature.attributes[window.outFields[0]];
fl.queryAttachmentInfos(feature.attributes[window.outFields[0]], lang.hitch(this, function(results){
if(results.length === 0){
window.attRsltCnt++;
var row = window.data.find(x => x.id === oid);
var indx = window.data.indexOf(row);
window.data.fill(row.Attachment='', indx, indx++);
//only update the grid store in 25 record increments
if(Number.isInteger(window.attRsltCnt / 25)){
memStore = new Memory({ data: window.data });
window.grid.set("store", memStore);
};
}else{
window.attRsltCnt++;
var row2 = window.data.find(x => x.id === oid);
var indx2 = window.data.indexOf(row);
window.data.fill(row2.Attachment=results[0].url, indx2, indx2++);
memStore = new Memory({ data: window.data });
window.grid.set("store", memStore);
}
if((window.resultsLen - 1) === window.attRsltCnt){
memStore = new Memory({ data: window.data });
window.grid.set("store", memStore);
setTimeout(function(){
window.grid.refresh();
}, 200);
}
}), oid);
return {
// property names used here match those used when creating the dgrid
"id": feature.attributes[window.outFields[0]],
"PPIN": feature.attributes[window.outFields[1]],
"NAME": feature.attributes[window.outFields[2]],
"Attachment": "Getting Attachment Info..."
};
});
var memStore = new Memory({ data: window.data });
window.grid.set("store", memStore);
});
}

...

function makeLink(data) {
if(data === "Getting Attachment Info..." || data === ""){
return data;
}else{
return "<a target=\"_blank\" href=\"" + data + "\">" + data + "</a>";
}
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
Highlighted
New Contributor III

Awesome, thank you!! This is extremely helpful, There aren't too many examples of this sort that I could find. 

Jim Faron

Reply
0 Kudos