Tuesday, May 21, 2013

Custom Control for custom layout of checkboxes

In a recent project, I wanted to create an interface to toggle different settings for different user types in an app. To save real estate on the page and (hopefully) make it more intuitive, I wanted to have a column per user type, and organize the checkboxes vertically.

I couldn't find any way to do this out of the box. To make it work, I made a regular checkbox group per field. Then in a repeat control, I have regular HTML checkboxes with name fetched from the real checkbox group. The checkbox group has to have the same values as the HTML checkboxes, or the values will be discarded.

The checkbox component is removed from the DOM via javascript when the page loads. If the real checkbox component isn't removed, you will only be able to select, and not deselect.

Screenshot from the demoapp (each checkbox column is bound to a multivalue field):

The custom control has four properties:
  • checkboxValues: Array of strings - Values for the checkboxes
  • fieldNames: Array of strings - Names of the fields in the form you want to connect the checkboxes to (remember to set them to multi-value in form)
  • headerLabels: Array of strings - Header labels for the checkbox columns
  • rowLabels: Array of strings - Labels for the checkbox rows

Currently, the custom control uses currentDocument to bind the fields. If the control doesn't work, you might need to use a more specific document data source.

Example usage
<xc:CheckboxTable checkboxValues="#{javascript:return ['inbox','outbox'];}"
   fieldNames="#{javascript:return ['hidden_items_administrators','hidden_items_users','hidden_items_limited_users'];}"
   headerLabels="#{javascript:return [labels.administrators, labels.users, labels.limitedUsers];}" rowLabels="#{javascript:return [labels.inbox,labels.outbox];}" />
The demoapp has been tested/works in these browsers: IE8/9 (should work in earlier browsers, but the layout is ugly), latest versions of Chrome, Firefox and Opera.

>> Download demoapp

The technique I used (real+"fake" checkboxes) should enable you to customize the layout of checkboxes however you want. I imagine the technique should also work for radio buttons.