Wednesday, November 14, 2012

Dojo DataGrid with Select Widget Formatter (Options)

I ran into quite a nasty issue today.

I have a dojo DataGrid I'm using to get user entry.  One of the fields was a text field, but my customer asked for it to be a drop down (Select) instead.  It was easy to add the select to the grid using the formatter option like this:


_layout.unshift({
'name' : 'Car',
'field' : 'car',
'editable' : false,
'width' : '65px',
'formatter' : _makeSelect
});
_editGrid = new dojox.grid.DataGrid({
singleClickEdit : true,
store : _editGridStore,
structure : _layout
});

The _layout has more fields, but you get the idea.  Then I created a _makeSelect function like this:


var _makeSelect = function(data, index, cell) {
var select = new dijit.form.Select({
           options: _cars,
           value: data,
       });
select._destroyOnRemove=true;
return select;
};


OK.  Take note of the options.  I'm using an array (_cars) of label/value objects that I set up earlier.  Each row in the grid will get this same options object.

I started having an issue where changing a value in one of the selects, would change the value in any other select that I clicked on!  It was driving me crazy!  I used a reductive process to start removing code until I came up with a small example/test file that I could reproduce the test with.  I ended up reproducing the issue/problem with only 2 Selects and no DataGrid at all.  See the problem was that I was using the same object for the options.  The dojo Select widget does not copy the options, but just takes what you give it.  (Google js references).  I have not fixed my code yet, but even if I was to use slice to copy my array, the objects (label/value) in the array would NOT get copied.  The object reference would get copied, so it would be a reference to an object in a DIFFERENT array!

Morale: Always give a unique options object to a dijit Select.  Stay sane!

PS: Could dojo "fix" this?  Maybe...

Monday, November 5, 2012

Dojo widgets always have a dom node

I am making a DataGrid with one column being a file upload column.

I was running into issues with this code because of a bad assumption on my part.  I thought the Form would not get added to the dom right away and it would not have a domNode until it was added to the page somewhere as a child.  That's not the case.  Once you construct a dijit, it has a domNode, although it may be "disconnected".  The reason I am not adding the Form to a domNode right away is that I am returning it and using it as the widget in a DataGrid using the formatter attribute.



var _form = new dijit.form.Form({
method : 'post',
enctype : 'multipart/form-data',
class : 'Uploader'
});
var _uploader = new dojox.form.Uploader(_dojoUploaderArgs);
_uploader.placeAt(_form.domNode);
_uploader._destroyOnRemove = true;

var _fileList = new dojox.form.uploader.FileList({
uploader : _uploader
});
_fileList.placeAt(_form.domNode);
_fileList._destroyOnRemove = true;

var _button = new dijit.form.Button({
type : 'submit',
label : 'Upload',
onClick : function() {
_uploader.upload();
}
});
_button.placeAt(_form.domNode);
_button._destroyOnRemove = true;

_button.startup();
_uploader.startup();
_fileList.startup();