Ext JS, Checkboxes, and Ruby on Rails

I am currently building a web application that makes heavy use of wizards and forms built with Ext JS. I am sending the form's values as JSON over to a Ruby on Rails server. Thanks to Rails 2.2.2, the JSON is automatically converted into an parameter hash.

For a little background to the problem I am about to describe, HTML checkboxes are notoriously difficult to work with, because if the user does *not* check the box, then the browser will not send a value when the form is submitted. This makes it difficult to handle a state change from checked to unchecked.

Rails makes this a bit easier because it will render both a hidden field with a value of "off" as well as the original checkbox. If the user checks the box, both values are sent but Rails will use the value from the checkbox (and not the hidden field). If the user does not check a box, only the hidden field's value is sent, which means the "off" value is sent.

However, when using Ext JS to render the form and its checkboxes, no hidden "off" field is rendered. Our first inclination is to extend the checkbox component to also render a hidden "off" field, much like Rails. However, because I am serializing the form as JSON, this strategy breaks down because the serialization will create an array of values for the checkbox and hidden field combo. This is because the fields are both named the same thing (exactly what the Rails code does) and when form serialization occurs, it will create an array if it encounters more than one value for a field name.

Instead of rendering a hidden "off" field for checkboxes, I simply change the way I am serializing the form. After serialization, I loop back through the form, find all the checkboxes, and for those checkboxes that are unchecked, I add an "off" value into my JSON serialization.

The code for this is much more simple than it sounds, and lets me always send checkbox values, regardless if they are checked or unchecked.

var serializedForm = card.getForm().getValues(false);

// because unchecked checkboxes do not submit values, manually force a value of 0
card.getForm().items.each(function(f) {
if (f.isFormField && f.getXType() == 'checkbox' && !f.getValue()) {
serializedForm[f.getName()] = '0';

Popular posts from this blog