I have two layers. I want to query staffLayer based on the a buffer of a selected feature in alertLayer. I am looking at Select with Feature Layer | ArcGIS API for JavaScript for an example. The difference is I don't want a map click, I want to select the feature in alertLayer based on a row in a grid.
I'm getting a feature from alertLayer with my grid click. I then need to buffer it, then use that buffer as the input geometry for a Query on staffLayer. I am getting as far as generating a circle based on the selected row, which draws in the correct location. However, I'm never getting any features found in that circle, even though I see there are several in the vicinity that should be returned.
I have changed this around several times, and I know I have a scope problem with the sequence of what I'm trying to do. I started out with something more straight forward, but changed to more a lang.hitch type of syntax, which I'm still getting the hang of.
I'm getting the error Uncaught TypeError: app.staffLayer.on(...).then is not a function
updateAlertGrid: function(){
var queryParams = new Query();
queryParams.geometry = app.currentExtent;
queryParams.spatialRelationship = Query.SPATIAL_REL_CONTAINS;
queryParams.outFields = ["*"];
queryParams.outSpatialReference = app.spatialReference;
var queryTask = new QueryTask(app.alertLayer.url);
queryTask.on('error', queryErrorHandler);
queryTask.execute(queryParams, lang.hitch(this, updateGridHandler));
function updateGridHandler(results){
var data = [];
if (app.alertGrid) {
app.alertGrid.refresh();
}
data = arrayUtils.map(results.features, function(feature){
return feature.attributes;
});
var currentMemory = new Memory({
data: data,
idProperty: 'ESRI_OID'
});
app.alertGrid.set("store", currentMemory);
app.alertGrid.sort('FlagStatusCode');
app.alertGrid.on('.dgrid-row:click', function(event){
var row = app.alertGrid.row(event);
var gridQuery = new Query();
gridQuery.objectIds = [row.data.ESRI_OID];
app.alertLayer.selectFeatures(gridQuery, FeatureLayer.SELECTION_NEW, function(results){
if (results.length > 0) {
app.alertFeature = results[0];
app.alertFeature.setInfoTemplate(app.alertTemplate);
// map.centerAndZoom(results[0].geometry,14);
var resultGeometry = results[0].geometry;
app.map.infoWindow.setFeatures(results);
app.map.infoWindow.show(resultGeometry);
}
else {
console.log("error in grid.on click function");
}
});
});
on(app.alertGrid, ".dgrid-cell:click", function(evt){
var cell = app.alertGrid.cell(evt);
var col = cell.column;
//var row = cell.row;
if (col.field === 'staff') {
// console.log("you clicked the staff cell");
findStaffbyLocation(app.alertFeature.geometry);
}
});
}
function queryErrorHandler(err){
console.log("error in queryTask is " + err.error);
}
//functions for finding staff near a server alert
function findStaffbyLocation(geom){
var circle = new Circle({
center: geom,
geodesic: true,
radius: 50,
radiusUnit: "esriMiles"
});
var circleSymb = new SimpleFillSymbol(SimpleFillSymbol.STYLE_NULL, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SHORTDASH, new Color([105, 105, 105]), 2), new Color([255, 255, 0, 0.25]));
var graphic = new Graphic(circle, circleSymb);
app.map.graphics.add(graphic); //circle is added correctly around the selected row
app.map.setExtent(circle.getExtent());
var query = new Query();
query.geometry = circle.getExtent();
app.staffLayer.queryFeatures(query);
app.staffLayer.on( 'query-features-complete', lang.hitch(this, function(response){ //there are never any features found here
var feature;
var features = response.features;
var inBuffer = [];
//started with extent,now filter out features that are not actually within buffer
for (var i = 0; i < features.length; i++) {
feature = features;
if (circle.contains(feature.geometry)) {
inBuffer.push(feature.attributes[ESRI_OID]);
}
}
})).then(function(){
var query = new Query();
query.objectIds = inBuffer;
var staffList = [];
app.staffLayer.selectFeatures(query, FeatureLayer.SELECTION_NEW, function(results){
arrayUtils.forEach(results, function(feature){
staffList.push(feature.attributes.Contact_FirstName + " " + feature.attributes.Contact_LastName + "</br>");
});
alert("Staff near selected server: " + staffList);
});
});
}
}
The dojo/on does not return a promise so, cannot use .then. Try changing that and see if it works.
I changed it around, but I still have no results from querying my circle's extent. I don't have these features turned on when I run the query, but I didn't think that would matter. I notice when I run it a 2nd time, I will sometimes get results when I didn't before.
I'm not getting an error, but still no results,
updateAlertGrid: function(){ var queryParams = new Query(); queryParams.geometry = app.currentExtent; queryParams.spatialRelationship = Query.SPATIAL_REL_CONTAINS; queryParams.outFields = ["*"]; queryParams.outSpatialReference = app.spatialReference; var queryTask = new QueryTask(app.alertLayer.url); queryTask.on('error', queryErrorHandler); queryTask.execute(queryParams, lang.hitch(this, updateGridHandler)); function updateGridHandler(results){ var data = []; if (app.alertGrid) { app.alertGrid.refresh(); } data = arrayUtils.map(results.features, function(feature){ return feature.attributes; }); var currentMemory = new Memory({ data: data, idProperty: 'ESRI_OID' }); app.alertGrid.set("store", currentMemory); app.alertGrid.sort('FlagStatusCode'); app.alertGrid.on('.dgrid-row:click', function(event){ var row = app.alertGrid.row(event); var gridQuery = new Query(); gridQuery.objectIds = [row.data.ESRI_OID]; app.alertLayer.selectFeatures(gridQuery, FeatureLayer.SELECTION_NEW, function(results){ if (results.length > 0) { app.alertFeature = results[0]; app.alertFeature.setInfoTemplate(app.alertTemplate); // map.centerAndZoom(results[0].geometry,14); var resultGeometry = results[0].geometry; app.map.infoWindow.setFeatures(results); app.map.infoWindow.show(resultGeometry); } else { console.log("error in grid.on click function"); } }); }); on(app.alertGrid, ".dgrid-cell:click", function(evt){ var cell = app.alertGrid.cell(evt); var col = cell.column; //var row = cell.row; if (col.field === 'staff') { // console.log("you clicked the staff cell"); findStaffbyLocation(app.alertFeature.geometry); } }); } function queryErrorHandler(err){ console.log("error in queryTask is " + err.error); } //functions for finding staff near an address function findStaffbyLocation(geom){ var circle = new Circle({ center: geom, geodesic: true, radius: 25, radiusUnit: "esriMiles" }); var circleSymb = new SimpleFillSymbol(SimpleFillSymbol.STYLE_NULL, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SHORTDASH, new Color([105, 105, 105]), 2), new Color([255, 255, 0, 0.25])); var graphic = new Graphic(circle, circleSymb); app.map.graphics.add(graphic); app.map.setExtent(circle.getExtent()); var cirquery = new Query(); cirquery.geometry = circle.getExtent(); // app.staffLayer.queryFeatures(cirquery); app.staffLayer.queryFeatures(cirquery,lang.hitch(this, function(response){ var feature; var features = response.features; app.inBuffer = []; //started with extent,now filter out features that are not actually within buffer for (var i = 0; i < features.length; i++) { feature = features; if (circle.contains(feature.geometry)) { app.inBuffer.push(feature.attributes.ESRI_OID); } } var query = new Query(); query.objectIds = app.inBuffer; var staffList = []; app.staffLayer.selectFeatures(query, FeatureLayer.SELECTION_NEW, function(results){ arrayUtils.forEach(results, function(feature){ staffList.push(feature.attributes.Contact_FirstName + " " + feature.attributes.Contact_LastName ); }); alert("Staff near selected server: " + staffList); }); })); } }
I am not sure why you are doing the query twice, may be for selection. In any case I made some changes yo your implementation. I believe the app.alertFeatureGeometry is not being set properly and this what I usually do, I append the geometry along with the attributes and pass it to dgrid, this I will be able to get access to the geometry on click event. see if this helps you.
PS: Make sure the dgrid is not showing the geometry column.
updateAlertGrid: function(){ var queryParams = new Query(); queryParams.geometry = app.currentExtent; queryParams.spatialRelationship = Query.SPATIAL_REL_CONTAINS; queryParams.outFields = ["*"]; queryParams.outSpatialReference = app.spatialReference; var queryTask = new QueryTask(app.alertLayer.url); queryTask.on('error', queryErrorHandler); queryTask.execute(queryParams, lang.hitch(this, updateGridHandler)); function updateGridHandler(results){ var data = []; if (app.alertGrid) { app.alertGrid.refresh(); } data = arrayUtils.map(results.features, function(feature){ //changed here to create a clone and merge the geometry to the data source var clone = lang.clone(feature.attributes); return lang.mixin( clone, { geometry : feature.geometry }); }); var currentMemory = new Memory({ data: data, idProperty: 'ESRI_OID' }); app.alertGrid.set("store", currentMemory); app.alertGrid.sort('FlagStatusCode'); app.alertGrid.on('.dgrid-row:click', function(event){ var row = app.alertGrid.row(event); var gridQuery = new Query(); gridQuery.objectIds = [row.data.ESRI_OID]; app.alertLayer.selectFeatures(gridQuery, FeatureLayer.SELECTION_NEW, function(results){ if (results.length > 0) { app.alertFeature = results[0]; app.alertFeature.setInfoTemplate(app.alertTemplate); // map.centerAndZoom(results[0].geometry,14); var resultGeometry = results[0].geometry; app.map.infoWindow.setFeatures(results); app.map.infoWindow.show(resultGeometry); } else { console.log("error in grid.on click function"); } }); }); on(app.alertGrid, ".dgrid-cell:click", function(evt){ var cell = app.alertGrid.cell(evt); var col = cell.column; //var row = cell.row; if (col.field === 'staff') { // console.log("you clicked the staff cell"); findStaffbyLocation(row.data.geometry); //changed to used row geometry } }); } function queryErrorHandler(err){ console.log("error in queryTask is " + err.error); } //functions for finding staff near an address function findStaffbyLocation(geom){ var circle = new Circle({ center: geom, geodesic: true, radius: 25, radiusUnit: "esriMiles" }); var circleSymb = new SimpleFillSymbol(SimpleFillSymbol.STYLE_NULL, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SHORTDASH, new Color([105, 105, 105]), 2), new Color([255, 255, 0, 0.25])); var graphic = new Graphic(circle, circleSymb); app.map.graphics.add(graphic); app.map.setExtent(circle.getExtent()); var cirquery = new Query(); cirquery.geometry = circle.getExtent(); // app.staffLayer.queryFeatures(cirquery); app.staffLayer.queryFeatures(cirquery,lang.hitch(this, function(response){ var feature; var features = response.features; app.inBuffer = []; //started with extent,now filter out features that are not actually within buffer for (var i = 0; i < features.length; i++) { feature = features; if (circle.contains(feature.geometry)) { app.inBuffer.push(feature.attributes.ESRI_OID); } } var query = new Query(); query.objectIds = app.inBuffer; var staffList = []; app.staffLayer.selectFeatures(query, FeatureLayer.SELECTION_NEW, function(results){ arrayUtils.forEach(results, function(feature){ staffList.push(feature.attributes.Contact_FirstName + " " + feature.attributes.Contact_LastName ); }); alert("Staff near selected server: " + staffList); }); })); } }
I don't typically return the geometry from a query that's populating a grid. Somehow I didn't think it would be retained as part of the row object. I have the other query because I don't see how else I'm going to display the infoTemplate for the feature. Maybe you typically go about this some other way. I added returnGeometry from my initial query, but I'm not still getting any results from
app.staffLayer.queryFeatures(cirquery,lang.hitch(this, function(response){
The length of the response is always 0. All my layers are in wkid 102100. At first I thought I wasn't getting anything because I my spatialReferences didn't go together, but the coordinates all look to match up.
I'm going to try to post something for people to look at. The initial project contains sensitive data, which is all secured.
Hi Tracy,
I don't believe 'on' is a deferred type which means the .then function won't exist. dojo's on module takes an event name and a callback function. You may be able to move that code in the then into the callback function like below:
app.staffLayer.on( 'query-features-complete', lang.hitch(this, function(response){ //there are never any features found here var feature; var features = response.features; var inBuffer = []; //started with extent,now filter out features that are not actually within buffer for (var i = 0; i < features.length; i++) { feature = features; if (circle.contains(feature.geometry)) { inBuffer.push(feature.attributes[ESRI_OID]); } } var query = new Query(); query.objectIds = inBuffer; var staffList = []; app.staffLayer.selectFeatures(query, FeatureLayer.SELECTION_NEW, function(results){ arrayUtils.forEach(results, function(feature){ staffList.push(feature.attributes.Contact_FirstName + " " + feature.attributes.Contact_LastName + "</br>"); }); alert("Staff near selected server: " + staffList); }); }));
EDIT: Just noticed @thejus replied while I was typing, but we essentially are saying the same thing
My layer is initially turned off, but I have a TOC that lets the user change it. I notice that it consistently finds the points I expect once the layer is turned on.
I wouldn't expect the visibility to make a difference on whether or not queryFeatures works.