#15676 closed defect (invalid)
The onChange event of dijit.form.CheckBox is triggered before the onClick event of the outer DOM node.
Reported by: | siqi | Owned by: | Douglas Hays |
---|---|---|---|
Priority: | undecided | Milestone: | tbd |
Component: | Dijit - Form | Version: | 1.8.0b1 |
Keywords: | Cc: | ||
Blocked By: | Blocking: |
Description
<div onclick="console.log('div clicked');"> <input id="cb1" data-dojo-id="cb1" data-dojo-type="dijit/form/CheckBox" data-dojo-props='name:"cb1", value:"foo", onClick: function(value){console.log("CheckBox Clicked");}, onChange:function(value){console.log("CheckBox onChange")}'/> </div>
With above code, click on the checkbox, the console logs: CheckBox? Clicked -> div Clicked -> CheckBox? onChange. As in dijit/form/_FormWidgetMixin.js, onChange is triggered with a defer, it seems aim at some issues. But not sure whether such event order is intended.
_handleOnChange: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){ ... // defer allows hidden value processing to run and // also the onChange handler can safely adjust focus, etc this._onChangeHandle = this.defer( function(){ this._onChangeHandle = null; this.onChange(newValue); }); // try to collapse multiple onChange's fired faster than can be processed ... }
Change History (4)
comment:1 Changed 9 years ago by
Resolution: | → invalid |
---|---|
Status: | new → closed |
comment:2 Changed 9 years ago by
Doug, I totally agree that onChange shoud happend after onClick, what I feel confused is that the onChange event doesn't get triggered immediately after onClick (it is triggered asychronously). Let's have a look at following code snippet. It simply updates a global check box status map when the onChange even get triggered. When you click on the container of these check boxes, you can get the check status from the status map. Since the onChange event is triggered after the onClick event to the parent node, when you click on a checkbox, you can not get the correct value from the status map while the checked attribute does change correctly...
<script type="text/javascript"> dojo.require("dijit.form.CheckBox"); var itemStatus = {}; function updateStatusMap(){ console.log('updateStatusMap'); itemStatus[this.id] = this.checked; } function onContainerClick(){ console.log('onContainerClick'); debugger; } </script> </head> <body class="claro"> <div onclick="onContainerClick()"> <input id="cb1" data-dojo-type="dijit/form/CheckBox" data-dojo-props='onChange:updateStatusMap'/> <input id="cb2" data-dojo-type="dijit/form/CheckBox" data-dojo-props='onChange:updateStatusMap'/> <input id="cb3" data-dojo-type="dijit/form/CheckBox" data-dojo-props='onChange:updateStatusMap'/> </div>
comment:3 follow-up: 4 Changed 9 years ago by
Mixing native synchronous events with asynchronous widget pseudo-events will introduce races that you don't want. I would recommend only using Dojo pseudo-events which will also reduce the number of event handlers as well:
dojo.ready(function(){ dojo.on( dojo.byId("pz"), "attrmodified-checked", function(evt){ var widget = dijit.byNode(evt.target); console.log('updateStatusMap'); itemStatus[widget.id] = widget.checked; onContainerClick(); } ) }); ... <div id="pz"> <input id="cb1" data-dojo-type="dijit/form/CheckBox"/> <input id="cb2" data-dojo-type="dijit/form/CheckBox"/> <input id="cb3" data-dojo-type="dijit/form/CheckBox"/> </div>
comment:4 Changed 9 years ago by
Replying to doughays: Yes, the 'attrmodified-checked' event can be used to solve the problem. But as I know, it's introduced in dojo 1.8, so I'm afraid it doesn't work in dojo 1.7... Actually, I just don't want to drop native events for using Dojo pseudo-events... Don't understand why the onChange event of CheckBox? is asynchronous though it maybe useful for some widgets such as slider...
Mixing native synchronous events with asynchronous widget pseudo-events will introduce races that you don't want. I would recommend only using Dojo pseudo-events which will also reduce the number of event handlers as well:
dojo.ready(function(){ dojo.on( dojo.byId("pz"), "attrmodified-checked", function(evt){ var widget = dijit.byNode(evt.target); console.log('updateStatusMap'); itemStatus[widget.id] = widget.checked; onContainerClick(); } ) }); ... <div id="pz"> <input id="cb1" data-dojo-type="dijit/form/CheckBox"/> <input id="cb2" data-dojo-type="dijit/form/CheckBox"/> <input id="cb3" data-dojo-type="dijit/form/CheckBox"/> </div>
It is intended that onChange happens after onClick of the CheckBox?. There's no contract about the order of onChange wrt bubbled click events to parent nodes.