Select to view content in your preferred language

Context of 'this' gets lost while adding graphic to map

1048
3
Jump to solution
12-19-2013 10:41 AM
JimWharton
Occasional Contributor
I have declared a class that adds a draw toolbar and an edit toolbar and an UndoManager.

define([   "dojo/on",   "dojo/dom",   "dojo/_base/event",   "dojo/_base/declare",   "dijit/_WidgetBase",   "dijit/_TemplatedMixin",   "dojo/text!./templates/DrawingToolsWidget.html",    "esri/toolbars/draw",   "esri/toolbars/edit",   "esri/graphic",    "esri/symbols/SimpleMarkerSymbol",   "esri/symbols/SimpleLineSymbol",   "esri/symbols/SimpleFillSymbol",   "esri/geometry/Point",   "esri/geometry/Polygon",   "esri/geometry/jsonUtils",   "esri/undoManager",   "dojo/_base/Color",    "dojo/domReady!" ],   function(     on,     dom,     Event,     declare,     _WidgetBase,     _TemplatedMixin,     template,     Draw,     Edit,     Graphic,     SimpleMarkerSymbol,     SimpleLineSymbol,     SimpleFillSymbol,     Point,     Polygon,     geometryJsonUtils,     UndoManager,     Color) {      return declare("DrawingToolsWidget",[_WidgetBase, _TemplatedMixin], {       templateString: template,       map:{},       toolbar:{},       symbol:{},       editToolbar:{},       selected:{},       currentLocation:{},       undoManager:{},        constructor: function(map) {         this.map = map;         this.undoManager = new UndoManager();       },       postCreate: function() {         console.log(this.undoManager);         this.createToolbar();       },       chooseTool: function(e) {         Event.stop(e);         var tool = e.target.id;         console.log(tool);         this.activateTool(tool);       },       activateTool: function(tool) {         // tool = tool.toUpperCase().replace(/ /g, "_");         this.toolbar.activate(Draw[tool]);         this.map.hideZoomSlider();       },       chooseMoveTool: function(e) {         Event.stop(e);         var self = this;         this.toolbar.deactivate();         self.editToolbar = new Edit(this.map);         // this.editToolbar.deactivate();         this.map.graphics.on("click", function(evt) {           self.selected = evt.graphic;           // console.log(self.selected);           self.editToolbar.activate(Edit.MOVE, evt.graphic);         });        },       chooseDeleteTool: function(e) {         Event.stop(e);         var self = this;         this.toolbar.deactivate();         this.map.graphics.on("click", function(evt) {           map.graphics.remove(evt.graphic);         });       },       createToolbar: function() {         this.toolbar = new Draw(this.map);         this.toolbar.on("draw-end", this.addToMap);       },       undo: function(e) {         Event.stop(e);         this.undoManager.undo();       },       redo: function(e) {         Event.stop(e);         this.undoManager.redo();       },       addToMap: function(evt) {         var symbol;         console.log(this.undoManager);         // this.toolbar.deactivate();         this.map.showZoomSlider();         switch (evt.geometry.type) {           case "point":           case "multipoint":             symbol = new SimpleMarkerSymbol();             break;           case "polyline":             symbol = new SimpleLineSymbol();             break;           default:             symbol = new SimpleFillSymbol();             break;         }         var graphic = new Graphic(evt.geometry, symbol);         var operation = this.map.graphics.add(graphic);         this.undoManager.add(operation); //<-- this returns undefined, but the reference to this.map above it is fine.       },       deactivateToolbar: function(e) {         Event.stop(e);         this.toolbar.deactivate();       }      });    }  );


When I set a breakpoint or console.log out the 'this' object in the addToMap method, I get the 'Window' object. Which makes me wonder why 'this.map' is working just fine.

How can I get the context of 'this' to be the class I've declared so I can push an operation onto the UndoManager's stack?
0 Kudos
1 Solution

Accepted Solutions
ReneRubalcava
Esri Frequent Contributor
Odd, I would think the context for this would the toolbar, but you can bind the context of your widget to the addToMap function using dojo/_base/lang.

Instead of
this.toolbar.on("draw-end", this.addToMap);

Try
this.toolbar.on("draw-end", lang.hitch(this, "addToMap"));


That should make sure your addToMap method has a context bound the widget.

View solution in original post

0 Kudos
3 Replies
ReneRubalcava
Esri Frequent Contributor
Odd, I would think the context for this would the toolbar, but you can bind the context of your widget to the addToMap function using dojo/_base/lang.

Instead of
this.toolbar.on("draw-end", this.addToMap);

Try
this.toolbar.on("draw-end", lang.hitch(this, "addToMap"));


That should make sure your addToMap method has a context bound the widget.
0 Kudos
JianHuang
Deactivated User
As Rene pointed out, it should be hitched.
The reason you are seeing that this.map is still available is probably you have map as a global variable defined in your application.
0 Kudos
JimWharton
Occasional Contributor
Thank you both for the insight. I do usually keep 'map' in a global while developing so that it's easy to just peek at it on the dev console.

And yes, dojo.hitch did the trick. I never really knew what that was for, so thanks for the quick lesson.

-Jim
0 Kudos