0

I am using the dojo toolkit for this project. I have a drop down button which has a Menu as a child that then has various menu Items. Since this will be a "living" application, the menu items will change as the business grows. My aim here is to have the ability to create event listeners for all menu items contained by the Menu. Dojo provides an accessor function "getChildren()" that I use to produce an object of all Menu Items that I would like to loop through. The Menu item has both a label and id that I would like to be able to work with if and when that item is selected. (NOTE: Buttons, Menu and Menu Items are contained by another script but are stored globally in an array named layout, in the same way I append functions and vars to the main = [] bellow.)

main = [];


require([
"dojo/dom","dojo/on","dojo/parser","dojo/json","dojo/domReady!"

], function(dom,on,parser,JSON) {

parser.parse();

console.log("Main Start");

//flags

//Listeners

var gpMenuChildren = layout.gpMenu.getChildren();
for (i in gpMenuChildren) {
    var id = gpMenuChildren[i].id;
    var label = gpMenuChildren[i].label;
    console.log(label);
    console.log(id);
    on(dom.byId(id),"click",function() {
        console.log("dom node w/ 'id' of " + id +" was clicked!");
        layout.gpButton.set("value",label);
        main.updateQueryStr();

    });
}

main.updateQueryStr = function updateQueryStr() {
    console.log("updateQueryStr called...");
    layout.cpCentTop.set("content", "Test updateQueryStr");
};


 console.log("Main End");

});

Through console.log() i can confirm that the individual ids and labels are correct and we can successfully loop through the children through this method.

HERE IS THE PROBLEM

The event listeners are successfully connected to each item in the menu list, however the function component of the listener appears to be overwriting every time and consequently only takes on the properties (id and label) of the last child in the loop. In other words the same id and label values are recorded for every menu item when clicked.

Any thoughts as to ensure the creation of independent event listeners that can contain the appropriate values from the children?

Thanks in advance!

LCaraway
  • 1,257
  • 3
  • 20
  • 48
  • 1
    Though using `this` solved your problem, to understand the root of what you've faced, please read [JavaScript closure inside loops – simple practical example](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – Teemu Feb 16 '16 at 15:34

2 Answers2

0

It happens because the content of variables changes. You can retrieve the id and label directly from the object, using this:

console.log("dom node w/ 'id' of " + this.id +" was clicked!");
        layout.gpButton.set("value",this.label);
Juan
  • 131
  • 1
  • 7
  • this.id returns the proper id, however this.label returns undefined. Which is odd to me because the Statement "var label = gpMenuChildren[i].label;" returns correctly, just as "var id = gpMenuChildren[i].id;" does too .. Shouldn't the label portion preform the same as the "id" portion? – LCaraway Feb 16 '16 at 15:55
  • try twith 'this.getAttribute("label")' – Juan Feb 16 '16 at 17:03
0

Was able to solve the problem of closures and scope by simply passing the variables from my loop into an outside function that then does what it needs to with the data (create an Event Listener).

    main.createListener = function createListener (id,label) {
    console.log("createListener called...");
    on(dom.byId(id),"click", function () {
        console.log("dom node w/ 'id' of " + id +" and a label of " + label + " was clicked!");
        layout.gpButton.set("value",label);
        main.updateQueryStr(label);
        });
    };

    var gpMenuChildren = layout.gpMenu.getChildren();
    for (i in gpMenuChildren) {
        var id = gpMenuChildren[i].id;
        var label = gpMenuChildren[i].label;
        main.createListener(id,label);
    }
LCaraway
  • 1,257
  • 3
  • 20
  • 48