Our web map runs a spatial query based off X-Y values pulled from a user-supplied address. The spatial query then checks if the geocoded point lies within a given polygonal feature representing trash and recycling service areas and populates a DOM element with the given field value (e.g. Tuesday).
I am attempting to pass the spatial query results, which are returned later in the script, back to a previously called infoTemplate which the user obtains if they click on the geocoded address point. Thus, the user would be able to obtain their recycling schedule data either by review the relevant DOM element or by clicking on the blue pin displaying their searched for address.
The infoTemplate falls within the local scope of its function and I'm stumped on how to pass back to the infoTemplate the results from a later-run query.
Would this even be feasible? I've looked at deferred objects and infoWindows (see here Info window with deferred object | ArcGIS API for JavaScript ) but I'm not certain if that's even applicable.
Here's our initial code:
//add geocoded address point to map with infoTemplate function addPlaceGraphic(item, symbol) { map.graphics.clear(); var place = {}; var attributes, infoTemplate, pt, graphic; pt = item.feature.geometry; place.address = item.name; place.score = item.feature.attributes.score; // Graphic components attributes = { address: place.address, score: place.score, lat: pt.getLatitude().toFixed(2), lon: pt.getLongitude().toFixed(2) }; infoTemplate = new InfoTemplate("${address}", "Latitude: ${lat}<br/>Longitude: ${lon}"<br/>Score: ${score}); graphic = new Graphic(pt, symbol, attributes, infoTemplate); // Add to map map.graphics.add(graphic); map.centerAt(pt); runPWQuery(pt, trashLayer, "trash"); runPWQuery(pt, yardWasteLayer, "yardwaste"); runPWQuery(pt, recyclingLayer, "recycling"); } //add featureLayers here //run query against previously called FeatureLayers function runPWQuery(in_geometry , in_fl , in_container_id) { var query = new esri.tasks.Query(); query.returnGeometry = true; query.outFields = ["*"]; query.geometry = in_geometry; in_fl.queryFeatures(query, function (myresponse, io) { var temp_val; var values = []; var tstr; for (var il = 0; il < myresponse.features.length; il++) { if (myresponse.features[il].attributes["MONDAY"] == "Yes") { temp_val = "Monday"; } else if (myresponse.features[il].attributes["TUESDAY"] == "Yes") { temp_val = "Tuesday"; } else if (myresponse.features[il].attributes["WEDNESDAY"] == "Yes") { temp_val = "Wednesday"; } else if (myresponse.features[il].attributes["THURSDAY"] == "Yes") { temp_val = "Thursday"; } else if (myresponse.features[il].attributes["FRIDAY"] == "Yes") { temp_val = "Friday"; } else { //temp_val = "Other"; temp_val = myresponse.features[il].attributes["DESCRIPT"]; } } var statCount = myresponse.features.length; if (statCount >= 1) { $("#" + in_container_id).html(temp_val); } else { $("#" + in_container_id).html(""); } }, function (error) { console.log(dojo.toJson(error, true)); }); } function renderPWQuery() { }
Thanks everyone for any help.
Solved! Go to Solution.
What you are trying can be achieved by using dojo/promise/all. I have made some changes to your code. make sure you add the require for all.
//add geocoded address point to map with infoTemplate function addPlaceGraphic(item, symbol) { map.graphics.clear(); var place = {}; var attributes, infoTemplate, pt, graphic; pt = item.feature.geometry; place.address = item.name; place.score = item.feature.attributes.score; var trashQuery = runPWQuery(pt, trashLayer, "trash"); var yardQuery = runPWQuery(pt, yardWasteLayer, "yardwaste"); var recycleQuery = runPWQuery(pt, recyclingLayer, "recycling"); all([trashQuery, yardQuery, recycleQuery]).then(function(results){ //the resutls you get will be for all the 3 queries. use the response as per your requirements //update the attributes here. // Graphic components attributes = { address: place.address, score: place.score, lat: pt.getLatitude().toFixed(2), lon: pt.getLongitude().toFixed(2) }; infoTemplate = new InfoTemplate("${address}", "Latitude: ${lat}<br/>Longitude: ${lon}"<br/>Score: ${score}); graphic = new Graphic(pt, symbol, attributes, infoTemplate); // Add to map map.graphics.add(graphic); map.centerAt(pt); }); } //add featureLayers here //run query against previously called FeatureLayers function runPWQuery(in_geometry , in_fl , in_container_id) { var query = new esri.tasks.Query(); query.returnGeometry = true; query.outFields = ["*"]; query.geometry = in_geometry; var promise = in_fl.queryFeatures(query, function(myresponse, io) { var temp_val; var values = []; var tstr; for (var il = 0; il < myresponse.features.length; il++) { if (myresponse.features[il].attributes["MONDAY"] == "Yes") { temp_val = "Monday"; } else if (myresponse.features[il].attributes["TUESDAY"] == "Yes") { temp_val = "Tuesday"; } else if (myresponse.features[il].attributes["WEDNESDAY"] == "Yes") { temp_val = "Wednesday"; } else if (myresponse.features[il].attributes["THURSDAY"] == "Yes") { temp_val = "Thursday"; } else if (myresponse.features[il].attributes["FRIDAY"] == "Yes") { temp_val = "Friday"; } else { //temp_val = "Other"; temp_val = myresponse.features[il].attributes["DESCRIPT"]; } } var statCount = myresponse.features.length; if (statCount >= 1) { $("#" + in_container_id).html(temp_val); } else { $("#" + in_container_id).html(""); } //return the value that needs to be displayed here return temp_val; }, function (error) { console.log(dojo.toJson(error, true)); }); //return the promise return promise; }
What you are trying can be achieved by using dojo/promise/all. I have made some changes to your code. make sure you add the require for all.
//add geocoded address point to map with infoTemplate function addPlaceGraphic(item, symbol) { map.graphics.clear(); var place = {}; var attributes, infoTemplate, pt, graphic; pt = item.feature.geometry; place.address = item.name; place.score = item.feature.attributes.score; var trashQuery = runPWQuery(pt, trashLayer, "trash"); var yardQuery = runPWQuery(pt, yardWasteLayer, "yardwaste"); var recycleQuery = runPWQuery(pt, recyclingLayer, "recycling"); all([trashQuery, yardQuery, recycleQuery]).then(function(results){ //the resutls you get will be for all the 3 queries. use the response as per your requirements //update the attributes here. // Graphic components attributes = { address: place.address, score: place.score, lat: pt.getLatitude().toFixed(2), lon: pt.getLongitude().toFixed(2) }; infoTemplate = new InfoTemplate("${address}", "Latitude: ${lat}<br/>Longitude: ${lon}"<br/>Score: ${score}); graphic = new Graphic(pt, symbol, attributes, infoTemplate); // Add to map map.graphics.add(graphic); map.centerAt(pt); }); } //add featureLayers here //run query against previously called FeatureLayers function runPWQuery(in_geometry , in_fl , in_container_id) { var query = new esri.tasks.Query(); query.returnGeometry = true; query.outFields = ["*"]; query.geometry = in_geometry; var promise = in_fl.queryFeatures(query, function(myresponse, io) { var temp_val; var values = []; var tstr; for (var il = 0; il < myresponse.features.length; il++) { if (myresponse.features[il].attributes["MONDAY"] == "Yes") { temp_val = "Monday"; } else if (myresponse.features[il].attributes["TUESDAY"] == "Yes") { temp_val = "Tuesday"; } else if (myresponse.features[il].attributes["WEDNESDAY"] == "Yes") { temp_val = "Wednesday"; } else if (myresponse.features[il].attributes["THURSDAY"] == "Yes") { temp_val = "Thursday"; } else if (myresponse.features[il].attributes["FRIDAY"] == "Yes") { temp_val = "Friday"; } else { //temp_val = "Other"; temp_val = myresponse.features[il].attributes["DESCRIPT"]; } } var statCount = myresponse.features.length; if (statCount >= 1) { $("#" + in_container_id).html(temp_val); } else { $("#" + in_container_id).html(""); } //return the value that needs to be displayed here return temp_val; }, function (error) { console.log(dojo.toJson(error, true)); }); //return the promise return promise; }
Much appreciated! One follow up question:
My query results aren't passing through to the graphic even though I've modified the attributes. I've reviewed the reference lit and the function executes and returns the graphic as well as passes the results to the DOM element.
Here are my attributes. Sorry for the formatting. Reply window won't let me format for syntax.
all([trashQuery, yardQuery, recycleQuery]).then(function (results) {
//the results you get will be for all the 3 queries. use the response as per your requirements
//update attributes; graphic components
attributes = { address: place.address, trashQuery: pt.trashLayer, yardQuery: pt.yardWasteLayer, recycleQuery: pt.recyclingLayer };
infoTemplate = new InfoTemplate("${address}", "Trash Pickup:${trashQuery}<br/><br/>Mixed Bulk: ${yardQuery}<br/><br/>Recycling Pickup: ${recycleQuery}");
graphic = new Graphic(pt, symbol, attributes, infoTemplate);