I know this issue has been done to death, but I still don't understand it. I've read StackOverFlow's very own "this" keyword explanation (along with the Mike West article within it) as well as other scope related questions. I don't know why I don't get it, so I look to the more savvy JavaScript developer for help.
From the code and comments it should be fairly self explanatory. But it is querying an ESRI map service, returning graphics and placing these on the map.
But the issue is in the showResults
function where I call this.graphics
, which is the map's graphics property (a graphics layer). I'm aware it's now out of scope (which took more time to figure out than I'd like to admit), but how can I put it back in scope so I can use it? Even if I have alter the code substantially...
define([
"dojo/_base/declare",
"dojo/on",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
"dijit/_WidgetsInTemplateMixin",
"dijit/form/Button",
"dijit/form/Form",
"dijit/form/FilteringSelect",
"dijit/form/ValidationTextBox",
"dojo/_base/array",
"dojo/_base/Color",
"dojo/_base/lang",
"esri/tasks/find",
"dojo/text!./Find/templates/Find.html"
], function(declare, on, _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, Button, Form, FilteringSelect, ValidationTextBox, array, Color, lang, find, FindTemplate) {
//anonymous function to load CSS files required for this module
(function() {
var css = [require.toUrl("gis/dijit/Find/css/Find.css")];
var head = document.getElementsByTagName("head").item(0),
link;
for(var i = 0, il = css.length; i < il; i++) {
link = document.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
link.href = css[i].toString();
head.appendChild(link);
}
}());
// Query Dijit
return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], {
widgetsInTemplate: true,
templateString: FindTemplate,
graphics: null,
findTask: null,
findParams: null,
results: [],
serverError: null,
queryLayer: null,
searchText: null,
postCreate: function() {
// Method is used to call a superclass method. It's good practice to assume that you are overriding a method that may
// do something important in a class up the inheritance chain
this.inherited(arguments);
// Create graphics layer and add it to the map
this.graphics = new esri.layers.GraphicsLayer({id:"queryGraphics"});
this.map.addLayer(this.graphics);
// Create find task with url to map service
this.findTask = new esri.tasks.FindTask("arcgis/rest/services/MapServer");
// Create find parameters and define known values
this.findParams = new esri.tasks.FindParameters();
this.findParams.outSpatialReference = this.map.spatialReference;
this.findParams.returnGeometry = true;
this.findParams.layerIds = [1];
this.findParams.searchFields = ["OBJECTID", "Gauge ID", "FV_ID", "FDC_ID", "Flood_Stage", "Flood_Line", "Municipality", "WATERSHED"];
// Listen for Submit button click
on(this.submitButton, 'click', lang.hitch(this, 'execute'));
},
// Submit button click event
execute: function execute() {
// Set the WHERE search text
this.findParams.searchText = dojo.byId("searchText").value;
// Sends a request to the ArcGIS REST map service resource to perform a search based
// on the FindParameters specified in the findParameters argument. On completion, the
// onComplete event is fired and the optional callback function is invoked.
this.findTask.execute(this.findParams, this.showResults, this.showError);
},
// Fires when the find operation is complete and returns an array of FindResult
showResults: function showResults(results) {
this.graphics.clear();
// Build an array of attribute information and add each found graphic to the map
dojo.forEach(results, function(result) {
var symbol;
switch(result.feature.geometry.type) {
case "point":
symbol = new esri.symbol.SimpleMarkerSymbol(esri.symbol.SimpleMarkerSymbol.STYLE_CIRCLE, 10, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new Color([255, 0, 0]), 1), new Color([255, 0, 0, 1.0]));
break;
case "polyline":
symbol = new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_DASH, new Color([255, 0, 0]), 1);
break;
case "polygon":
symbol = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_DASHDOT, new Color([255, 0, 0]), 2), new Color([255, 255, 0, 0.0]));
break;
default:
symbol = new esri.symbol.SimpleMarkerSymbol(esri.symbol.SimpleMarkerSymbol.STYLE_CIRCLE, 10, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new Color([255, 0, 0]), 1), new Color([255, 0, 0, 1.0]));
}
var graphic = new esri.Graphic(result.feature.geometry, symbol);
this.graphics.add(graphic);
});
},
// Fires if the find execution fails to complete
showError: function showError(serverError) {
alert("The server encountered an error. Error: " + serverError);
}
});
});
UPDATE AFTER ANSWERS:
So, it wasn't one answer that solved this but a combination of two. I incorporated Buffalo's answer of
this.findTask.execute(this.findParams, lang.hitch(this, this.showResults), this.showError);
and Buffalo's comment to Craig's answer of
dojo.forEach(results, function(result) {
...
}, this);
but Craig's would have worked here as well. This combined with Tamil's answer I'm most certain would have worked too.
So I'll mark Buffalo's as the answer, but all three are worth looking at for any further readers.