drawtoolbar can not activate

3836
12
Jump to solution
04-15-2016 02:31 PM
JunxuanZhao
New Contributor

Currently, we  want to create a custom widget to draw polygon on the map(arcgis web appbuilder 1.3). But it shows that the Uncaught TypeError: Can not read property 'activate' of undefined. (In Widget.js file )

The related line is drawToolbar.activate(esri.toolbars.Draw.POLYGON);  

Here is my code:

define(['dojo/_base/declare',

        'jimu/BaseWidget',

        'esri/urlUtils',

        'esri/config',

        'esri/map',

        'esri/graphic',          

        'esri/tasks/RouteTask',          

        'esri/tasks/RouteParameters',

        'esri/tasks/FeatureSet',          

        'esri/symbols/SimpleMarkerSymbol',

        'esri/symbols/SimpleLineSymbol', 

        'esri/Color',

        'dojo/_base/array',

        'dojo/on',

        'dojo/dom',

        'dojo/domReady!',

        'dijit/registry',

        'dijit/layout/BorderContainer',

        'dijit/layout/ContentPane',

        'dijit/form/HorizontalSlider',

        'dijit/form/HorizontalRuleLabels',

        'esri/toolbars/draw',

        'esri/tasks/GeometryService',

        'esri/symbols/SimpleFillSymbol',

        'esri/tasks/DataFile',

        'dojo/_base/connect'

  ],

    function(declare, BaseWidget,urlUtils, esriConfig, Map, Graphic, RouteTask, RouteParameters,

        FeatureSet, SimpleMarkerSymbol, SimpleLineSymbol,      

        Color, array, on, dom, registry,

        Draw, GeometryService,SimpleFillSymbol,DataFile,connect

  ) {

 

     return declare([BaseWidget], {

      baseClass: 'jimu-widget-MyWidget',

      name: 'MyWidget',

      startup: function(){

        var map, Draw, routeTask, routeParams, routes= [];

        var drawToolbar;

        var geometryService;

        var stopSymbol, barrierSymbol, polygonBarrierSymbol,routeSymbols;

        var mapOnClick_addStops_connect, mapOnClick_addBarriers_connect,mapOnClick_addPolygonBarriers_connect;

        geometryService = new        GeometryService("https://utility.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer");

        map = this.map;

        routeTask = new RouteTask("https://route.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World");

        routeParams = new RouteParameters();      

        routeParams.polygonBarriers = new FeatureSet();

        routeParams.outSpatialReference = {"wkid":102100};

       var polygonBarrierSymbol= new esri.symbol.SimpleFillSymbol();

        routeSymbols = {

          "Route 1": new SimpleLineSymbol().setColor(new Color([0,0,255,0.5])).setWidth(5),

          "Route 2": new SimpleLineSymbol().setColor(new Color([0,255,0,0.5])).setWidth(5),

          "Route 3": new SimpleLineSymbol().setColor(new Color([255,0,255,0.5])).setWidth(5)

        };

        on(dom.byId("addpolygonBarriersBtn"), "click", addpolygonBarriers);

        on(dom.byId("clearpolygonBarriersBtn"), "click", clearpolygonBarriers);

  

    function createToolBar(){        

        drawToolbar = new esri.toolbars.Draw(map);         

        drawToolbar.on("draw-end", addToMap);

        }

      

        function activateTool(){

        drawToolbar.activate(esri.toolbars.Draw.POLYGON);         

        map.hideZoomSlider();

        }

        

        function addToMap(evt) {

          drawToolbar.deactivate();         

          routeParams.polygonBarriers.features.push(           

          map.graphics.add(new esri.Graphic(evt.geometry, polygonBarrierSymbol)) );

        }

  

         

        var node = dojo.byId("addpolygonBarriersBtn");        

        dojo.connect(node, "click", activateTool);

     map.on("load", createToolBar);  

      //Begins listening for click events to add polygonbarriers

        function addpolygonBarriers() {

          removeEventHandlers();

          mapOnClick_addPolygonBarriers_connect = on(map, "onclick", addPolygonBarrier);

        }

      //Clears all polybarriers

        function clearpolygonBarriers() {

          removeEventHandlers();

          for (var i=routeParams.polygonBarriers.features.length-1; i>=0; i--) {

            map.graphics.remove(routeParams.polygonBarriers.features.splice(i, 1)[0]);

          }

        }

       // Add Polygon

        function addPolygonBarrier(evt) {

            drawToolbar.activate(esri.toolbars.Draw.POLYGON);        

            var drawEnd_connect = dojo.connect(drawToolbar, "onDrawEnd", function(geometry) {

            routeParams.polygonBarriers.features.push( map.graphics.add(new esri.Graphic(geometry, polygonBarrierSymbol)) );});

        }

  

 

        function removeEventHandlers() { 

          if (mapOnClick_addPolygonBarriers_connect) {

            mapOnClick_addPolygonBarriers_connect.remove();

          }

        }

  }

   

  });

  });

demo.png

Tags (1)
0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Juxuan,

  OK here is the edited and fully working version of your widget:

View solution in original post

12 Replies
RobertScheitlin__GISP
MVP Emeritus

Junxuan,

  Your biggest issue is that you have your requires and their subsequent parameters out of order. You should review this blog:

The abc’s of AMD | ArcGIS Blog

Each require has a parameter that the require is called by

i.e. "esri/map", "esri/toolbars/draw"],function(Map, Draw){

notice Map is first then Draw and the parameters match the same order.

dojo/domReady! should always be last in your requires and layout elements like 'dijit/layout/BorderContainer' that are used in your trmplate html but not in your js code should be right before dojo/domReady!

Your next issue is mixing Legacy and AMD Style coding (i.e. esri.toolbar.draw is Legacy). The parameter Draw is all you need to use when coding against the require for esri/toolbars/draw.

When building widgets you reference dom elements in the template by using data-dojo-attach-point="blah" and not id="blah". So there is no need for dom.byId("blah") instead you use this.blah.

If you are going to use dojo layout or form dijits in your template html then you need to have the require for 'dijit/_WidgetsInTemplateMixin' and it needs to be added to your declare too.

return declare([BaseWidget, _WidgetsInTemplateMixin], {

Here is a version of what you had using esri standard widget development practices:

JunxuanZhao
New Contributor

Hi Robert,

Thanks for your detail explanation and example.

Our final goal is to find the routes but avoid certain area or specific points. Currently, the widget works well except the routes can not be showed on the map. The error is can not read property 'push' of undefined in showRoute function(this.routes.push).

Attached is our code.

Thanks in advanced!

Junxuan

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Junxuan,

  This issue is that your array loop is out of scope and does not know what this.routes is. Adding lang.hitch as shown in line 4 will fix that.

showRoute:function(evt) {
      this.clearRoutes();

        array.forEach(evt.result.routeResults, lang.hitch(this, function(routeResult, i) {
            this.routes.push(
              this.map.graphics.add(
                routeResult.route.setSymbol(this.routeSymbols[routeResult.routeName])
              )
            );
          }));

Don't forget to mark this thread as answered by clicking on the correct answer link on the thread that answered your question.

0 Kudos
JunxuanZhao
New Contributor

Hi Robert:

Thanks for your information. I modified the showRoutes function code, but it still can not show the routes, even though it seems that there is no error.

showRoute:function(evt) {

           this.clearRoutes();

          array.forEach(evt.result.routeResults, lang.hitch(this, function(routeResult, i) {

              this.routes.push(

              this.map.graphics.add(

                routeResult.route.setSymbol(this.routeSymbols[routeResult.routeName])

              )

            );

          }));

 

   var msgs = ["Server messages:"];

              array.forEach(evt.result.messages, lang.hitch(function(message) {

              msgs.push(message.type + " : " + message.description); !

          }));

 

          if (msgs.length > 1) {

            alert(msgs.join("\n - "));

          }

        

          }

error.JPG

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Junxuan,

  So does the alert ever display? Looking at your code and the console screenshot it looks like you are not providing a token for the RouteTask.

0 Kudos
JunxuanZhao
New Contributor

Hi Robert,

I think I have provided a token for the Route Task. Do you mean the Interface like this?

login.JPG

Thanks,

Junxuan

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Yes, I did not see any identityManager stuff in your code.

Are you getting the Alert that you have setup in your code? If not then you are not getting any results to add to the map.

0 Kudos
JunxuanZhao
New Contributor

Currently, it is difficult for us to get your points.

1. What is Alert? How can I check that?

2. What does "identity manager stuff in code" mean? When I click the Solve Route Button, there is a pop-up window which asks me to enter the account information and that's it.

Thanks,

Junxuan

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Junxuan,

  In your code you have:

showRoute:function(evt) {

           this.clearRoutes();

          array.forEach(evt.result.routeResults, lang.hitch(this, function(routeResult, i) {

              this.routes.push(

              this.map.graphics.add(

                routeResult.route.setSymbol(this.routeSymbols[routeResult.routeName])

              )

            );

          }));

  

          var msgs = ["Server messages:"];

              array.forEach(evt.result.messages, lang.hitch(function(message) {

              msgs.push(message.type + " : " + message.description);

          }));

  

          if (msgs.length > 1) {

            alert(msgs.join("\n - "));

          }

},

If you are getting the login popup (identityManager) already then you can ignore that comment of mine.

0 Kudos