I had a need for a group of checkboxes that act as a single field, where the values and boxLabels of the checkboxes are retrieved from the server via an Ext.data.Store.
Code:
Ext.namespace('Ext.ux.form');
Ext.ux.form.CheckboxMultiSelect = Ext.extend(Ext.Panel, {
delimiter: ',',
displayField: 'text',
valueField: 'text',
hiddenField: null,
checkboxes: null,
autoScroll: true,
frame: true,
initComponent: function() {
Ext.ux.form.CheckboxMultiSelect.superclass.initComponent.call(this);
var me = this;
this.checkboxes = [];
this.initialConfig.store.on('load', function(store) {
var values = this.initialConfig.value ? this.initialConfig.value.split(me.delimiter) : [];
var vlen = values.length;
store.each(function(record) {
var d = me.displayField;
var v = me.valueField;
var checked = false;
for (var i=0; i<vlen; i++) {
if (''+record.data[v] === ''+values[i]) {
checked = true;
break;
}
}
me.checkboxes.push(me.add({
xtype: 'checkbox',
boxLabel: record.data[d],
inputValue: record.data[v],
hideLabel: true,
checked: checked,
listeners: {
check: function(cb, checked) {
me.setValue(me.getValue());
}
}
}));
});
this.doLayout();
}, this);
},
onRender: function(ct, position) {
Ext.ux.form.CheckboxMultiSelect.superclass.onRender.call(this, ct, position);
this.hiddenField = this.el.createChild({
tag: 'input',
type: 'hidden',
name: this.name,
value: this.value
});
this.initialConfig.store.load();
},
getValue: function() {
var values = [];
for (var i=0, len=this.checkboxes.length; i<len; i++) {
var cb = this.checkboxes[i];
if (cb.checked) {
values.push(cb.initialConfig.inputValue);
}
}
return values.join(this.delimiter);
},
setValue: function(v) {
this.hiddenField.dom.value = v;
}
});
Ext.reg('uxcheckboxmultiselect', Ext.ux.form.CheckboxMultiSelect);
displayField is the field in the Store's record that is displayed as boxLabel
valueField is the field in the Store's record that is returned if the checkbox is checked
It maintains a hidden field for submitting the combined values of the checkboxes. The value submitted is the valueField of each checkbox that is checked, joined, delimted by the delimeter config option.
Example: If you select 3 of 4 checkboxes and their valueFields are 1,3, and 5, and the delimeter is ',', then the submitted value would be "1,3,5"
The flaw in this extension is that it will also submit a key/value pair for the checkboxes, with field names like ext-gen-blah. If anyone has a suggestion on how to defeat this, I'd appreciate it.
Example usage:
Code:
var form = new Ext.form.FormPanel({
...
items: [
...
{
xtype: 'uxcheckboxmultiselect',
store: new Ext.data.Store({
...
}),
displayField: 'value_to_display',
valueField: 'value_to_submit'
}
...
]
...
});