Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I can't get onChange to fire for dijit.form.Select

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)?
like image 293
yarmiganosca Avatar asked Apr 01 '10 14:04

yarmiganosca


3 Answers

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.

like image 163
Nick Fenwick Avatar answered Nov 09 '22 22:11

Nick Fenwick


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.

like image 27
GoinOff Avatar answered Nov 09 '22 23:11

GoinOff


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.

like image 35
Kniganapolke Avatar answered Nov 09 '22 23:11

Kniganapolke