Custom widget variable scope

3995
5
Jump to solution
04-18-2016 06:08 AM
NartTamash
New Contributor III

Hi all,

Not a seasoned developer, so this might have a very simple answer that I'm failing to see/understand.

I'm trying to build a custom widget from scratch, and most of my code gets executed when a button is clicked in the widget interface (it's a portal map services search). I am using a global variable that needs to be manipulated at various stages (i.e. events). To keep this as short as possible my code looks something like this:

...

addedLayers: [], //This is the global variable

postCreate: ...

startup: ...

customFunctionOnButtOnclick: function() {

map = this.map;

var addedLayers = this.addedLayers;

...

       on(map, "layer-remove", function(event) {

            //do something to addedLayers

       });

       

       on(map, "layer-add", function(event) {

            //do something else to addedLayers

       });

},

...

Is there a reason why addedLayers can be accessed in the layer-add event but not in the layer-remove event?

I obviously only included the relevant parts of that main function. There are other bits that do different things, but none of which should affect addedLayers. Also the two map events, are in the same succession as presented here.

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Nart,

  Sure, it is a scoping issue as you have stated already. Each time you an event handler using dojo/on the scope of the handling function changes and you need to use lang.hitch to maintain the scope.

Add "dojo/_base/lang" require

customFunctionOnButtOnclick: function() {
  map = this.map;
  var addedLayers = this.addedLayers;
  ...
  on(map, "layer-remove", lang.hitch(this, function(event) {
     //do something to addedLayers
  }));
       
  on(map, "layer-add", lang.hitch(this, function(event) {
    //do something else to addedLayers
  }));
},

View solution in original post

5 Replies
RobertScheitlin__GISP
MVP Emeritus

Nart,

  Sure, it is a scoping issue as you have stated already. Each time you an event handler using dojo/on the scope of the handling function changes and you need to use lang.hitch to maintain the scope.

Add "dojo/_base/lang" require

customFunctionOnButtOnclick: function() {
  map = this.map;
  var addedLayers = this.addedLayers;
  ...
  on(map, "layer-remove", lang.hitch(this, function(event) {
     //do something to addedLayers
  }));
       
  on(map, "layer-add", lang.hitch(this, function(event) {
    //do something else to addedLayers
  }));
},
NartTamash
New Contributor III

Thanks Robert! This partially worked however. Interestingly, inside the layer-remove event (after layer-add has been fired once), I could access this.addedLayers, but not the variable I declared previously (i.e. var addedLayers = this.addedLayers). Why is that?

Another question...if I declare the local variable 'addedLayers' without the 'var' (i.e. addedLayers = this.addedLayers), and without using lang.hitch, the variable is accessible in both events, as is the local map variable (also declared without a var).

How does this work (both the scope and declaring variables without the 'var')? If it's too much, I'd also be happy if you could point me to a good resource that explains it.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Nart,

Using a the var makes a variable a local variable and not using var make the variable a global variable (this is not a good thing per-say).

...

addedLayers: [], //This is the global variable

postCreate: ...

startup: ...

above addedLayer is now a psuedo-global var that can be access using "this.addedLayer"

In WAB widget development if you want a var to be accessible in any function in the widget then you use addedLayers:[], like you have following the "return declare([BaseWidget, _WidgetsInTemplateMixin], {" line. And you access it using this.addedLayers but the function or arrays function loop has to maintain the same scope using lang.hitch.

There is absolutely no need to create a var for the map as all widgets have access to "this.map"

I am not sure why you are having problem accessing "this.addedLayers" array in the on "layer-remove" if the function is preceded by lang.hitch.

on(this.map, "layer-remove", lang.hitch(this, function(event) {

    //do something to addedLayers

   console.info(this.addedLayers);

}));

NartTamash
New Contributor III

Sorry, I might not have been very clear...I was refering to the 'addedLayers' declared with a 'var' inside the 'customFunctionOnButtonClick' section as described in the first post, not the one declare before startup, postcreate, etc.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Nart,

OK I am probably missing your question then. So here is a bit of advice.

Do not name your local vars and global vars the same. Because you do have them named the same it will get really confusing as to which one you are getting by using "this."

customFunctionOnButtOnclick: function() {
    //You don't need these next two lines as you can access the global versions of them by using "this."
    map = this.map;
    var addedLayers = this.addedLayers;
...
      on(map, "layer-remove", lang.hitch(this, function(event) {
            //do something to addedLayers
      }));
     
      on(map, "layer-add", lang.hitch(this, function(event) {
            //do something else to addedLayers
      }));
},