views:

1008

answers:

3

I seem unable to correctly attach the onchange event to a dijit.form.Select widget. However, I am new to web development, so I could be doing something completely idiotic (although, as best I can tell (and I've read all the docs I could find) I'm not). I made sure the body class matches the dojo theme, that I dojo.require() for all the widgets I use (and dojo.parser), and still, nada. The code I'm using is:

dojo.addOnLoad(function () {
    var _query = dojo.query('.toggle');
    for (var i in  _query) {
        dojo.connect(_query[i], 'onchange', function (ev) {
            console.log(ev + ' fired onchange');
        });
    }
});

Any help at all would be appreciated.

Addition: after digging more into the internals of how dijit renders widgets, I discoverd that when I add the dojoType='dijit.form.Select' attribute-value pair to my html element (doing this declaratively), dijit actually renders a one-row two-col table. The table's first element is a span (with the class dijitSelectLabel) that I'm assuming just displays the selected (or default) element. It's second element appears to be a button rendered as a down arrow that toggles the display of the menu itmes in response to certain DOM events. Also (and I thought this was pretty nifty), dijit doesn't actually place the select options in the DOM tree until one of those events is triggered. I looked at the HTML in firebug right after a fresh pageload (before i clicked on anything), and the second option isn't anywhere to be found. Then, once I click on the arrow button, there's a dijit.Menu widget, dijit sticks a dijit.Menu to the end of the body node; after I click somewhere else, the Menu widget is still the body's lastChild, now its just hidden and not attached to the form.Select widget.

Should it really be this complicated if all I want to do is place a different dijit.form widget in the DOM tree depending on what item the user selects?

Conclusion: Turns out it was a capitalization issue.

dojo.connect(widget_obj, 'onChange', function_obj);
works, whereas

dojo.connect(widget_obj, 'onchange', function_obj);
doesn't.

So I was right that I was being completely stupid. I assumed that because the all lowercase version works when putting placing in it an html tag as an attribute, that Dojo would treat it the same. It makes sense, because dijit.form.Select has no .onchange attribute, but does have a .onChange attribute. (I ended up sticking with a .Select over a .FilteringSelect because I don't my users to be given any impression that they can type in something.) So, which one of you guys do I give the answer to (because you both had onChange in your posts, I guess I was just too inexperienced to realize that the case mattered)?

+2  A: 

Try the following when doing a dojo.connect:

  var inputEvents = [];  //Global var

  inputEvents.push(dojo.connect(dijit.byId(inputFldStr), "onChange", eventFuncObj));

Store the connection in a global var.

GoinOff
I tried both dijit.byId(nodeId) and dijit.byNode(node) and neither approach worked.
yarmiganosca
A: 

In your code you connect a handler to 'onchange' event of dom nodes, not dojo widgets. dojo.query returns you a NodeList object - a collection of nodes that match the query.
In this case it's more reliable to connect to a widget's 'onChange' event, as GoinOff showed. Just a little addition to his answer to make sure you're doing this right.
Assume this is your html (in later versions of Dojo dijit.form.Select has been replaced with dijit.form.FilteringSelect):

<input dojoType="dijit.form.FilteringSelect" id="stateInput" store="stateStore" searchAttr="name" name="state"/>

Then you would connect to 'onChange' this way (you also can store the connection in some array to be able to disconnect it later, as GoinOff suggested):

dojo.addOnLoad (function () {
   dojo.connect(dijit.byId("stateInput"), "onChange", function(){});
}

But it's another story if you don't know your widget's id and want to use dojo.query to connect to multiple widgets.

Kniganapolke
This didn't work either (especially because the options rendered outside the widget until I changed it to <select dojoType...).
yarmiganosca
+1  A: 

For anyone else finding this page through a web search, you may have made the same mistake I did .. copy-pasting your markup such that each has the same 'value'.

e.g.

<select dojoType='dijit.form.Select' onChange="fn">
<option value='foo'>Foo 1</option>
<option value='foo'>Foo 2</option>
<option value='foo'>Foo 3</option>
</select>

fn() will never be called, because the change handler code checks the new value against the previously selected value and does not fire onChange unless it's changed.

Nick Fenwick
That's not actually the mistake I made. If you read the last part of the question (which I probably should have submitted as an answer, for clarity's sake), you'll see that I was mistakenly assuming because capitalization didn't matter in the markup (onchange vs. onChange) that it didn't matter in the code. Though I do thank you for making me aware of the issue you describe; I will file that away should I need it in future.
yarmiganosca
I wasn't responding to you, I was commenting for the sake of other people such as myself who found this page based on the broken behaviour your subject describes (onChange handler not firing) who had actually made a different mistake in their code.
Nick Fenwick