I've written a class that extends dijit.Tree to include a radio button alongside each node. I'm using it in a form to show a folder tree from which the user can select a folder. Here is the code:
define("my/Tree/RadioButton",
['dojo/_base/declare', 'dijit/Tree', 'dijit/form/RadioButton', 'dojo/dom-construct', 'dojo/_base/connect', 'dojo/on', 'dojo/_base/lang'],
function (declare, Tree, RadioButton, domConstruct, connect, on, lang){
var TreeNode = declare(Tree._TreeNode, {
_radiobutton: null,
postCreate: function(){
this._createRadioButton();
this.inherited(arguments);
},
_createRadioButton: function(){
this._radiobutton = new RadioButton({
name: this.tree.name,
value: this.tree.model.store.getIdentity(this.item) + '',
checked: false
});
domConstruct.place(this._radiobutton.domNode, this.iconNode, 'before');
if (this.tree.model.store.hasAttribute(this.item, 'checked')) {
var attrValue = this.tree.model.store.getValue(this.item, 'checked');
if (attrValue === true) {
this._radiobutton.set('checked', true);
}
}
connect.connect(this._radiobutton, 'onClick', this, function(){
// set any checked items as unchecked in the store
this.tree.model.store.fetch({
query: {checked: true},
onItem: lang.hitch(this.tree.model.store, function(item){
console.log('found checked item ' + this.getValue(item, 'name'));
this.setValue(item, 'checked', false);
})
});
// check the one that was clicked on
var radioValue = this._radiobutton.get('value');
this.tree.model.store.setValue(this.item, 'checked', true);
});
}
});
return declare(Tree, {
_createTreeNode: function(/*Object*/ args){
return new TreeNode(args);
}
});
});
The issue is that when the form is submitted, the value that is submitted is always the value of the first radio button that was selected, even if other radio buttons are subsequently clicked on.
I can see by inspecting the dom that the value attribute for the checked radio button has the correct value. But what gets submitted is always the initially selected value.
I have a similar class that uses the checkbox widget instead and that one works fine.
Edit based on some feedback I created an even simpler version of this class that doesn't track the checked state using attribute in the store:
define("my/Tree/RadioButton",
['dojo/_base/declare', 'dijit/Tree', 'dijit/form/RadioButton', 'dojo/dom-construct'],
function (declare, Tree, RadioButton, domConstruct){
var TreeNode = declare(Tree._TreeNode, {
_radiobutton: null,
postCreate: function(){
this._createRadioButton();
this.inherited(arguments);
},
_createRadioButton: function(){
this._radiobutton = new RadioButton({
name: this.tree.name,
value: this.tree.model.store.getIdentity(this.item) + '',
checked: false
});
domConstruct.place(this._radiobutton.domNode, this.iconNode, 'before');
}
});
return declare(Tree, {
_createTreeNode: function(/*Object*/ args){
return new TreeNode(args);
}
});
});
but even this still has the same issue - whichever radio button the user clicks on first is the value that will be submitted, regardless of what other buttons are subsequently clicked.
I managed to workaround this issue by hooking on to the onchange event for the radio buttons. The hook explicitly sets checked to false on the unchecked radio button, which seems to fix the problem. I'm unsure why this is required though.