PDA

View Full Version : Bug? Setting values for a CheckboxGroup modifies all other CheckboxGroups w/Same Name



charris
12 Oct 2011, 12:07 PM
I've noticed a problem with having multiple CheckboxGroups and think it might be a bug. So far I've only tested it in 4.0.2a and 4.0.6; the issue exists in both of those versions.

Say I'm displaying multiple tabs for editing different users. Each tab contains form panel with a CheckboxGroup for editing roles; something like this:

28643


Ext.define('myapp.view.admin.EditUserFormPanel', {
extend: 'Ext.form.Panel',
alias: 'widget.myapp.view.admin.EditUserFormPanel',
initComponent: function() {
var me = this;
me.bodyPadding = 10;
me.defaults = {
labelWidth: 100,
labelAlign: 'left'
};

me.items = [
{
xtype: 'textfield',
fieldLabel: 'Name',
name: 'name'
},
{
xtype: 'displayfield',
fieldLabel: 'Expected Roles',
name: 'expectedRoles'
},
{
xtype: 'checkboxgroup',
fieldLabel: 'Actual Roles',
columns: 1,
items: [
{ boxLabel: 'Role A', name: 'roles', inputValue:'roleA' },
{ boxLabel: 'Role B', name: 'roles', inputValue:'roleB' }
]
}
];

me.callParent();
}
});

Ext.define('myapp.model.UserModel', {
extend: 'Ext.data.Model',
fields: [
{name: 'firstName', type: 'string'},
{name: 'lastName', type: 'string'},
{name: 'roles', type: 'array'}
]
});

var model1 = Ext.create('myapp.model.UserModel');
model1.set('name', 'Pete Schweddy');
model1.set('expectedRoles', 'Role A, Role B');
model1.set('roles', ['roleA', 'roleB']);

var formPanel1 = Ext.create('myapp.view.admin.EditUserFormPanel', {
title:'User 1'
});
formPanel1.loadRecord(model1);

var model2 = Ext.create('myapp.model.UserModel');
model2.set('name', 'Matt Foley');
model2.set('expectedRoles', 'Role B');
model2.set('roles', ['roleB']);

var formPanel2 = Ext.create('myapp.view.admin.EditUserFormPanel', {
title:'User 2'
});
formPanel2.loadRecord(model2);

var tabPanel = Ext.create('Ext.tab.Panel', {
height: 150,
layout: 'fit',
renderTo: Ext.getBody(),
items: [ formPanel1, formPanel2 ]
});

console.log(Ext.form.CheckboxManager.getByName('roles'));

The problem is that the 'Actual Roles' checkbox group for User 1 is always set to the roles for User 2. You can run/modify this code example here: http://jsfiddle.net/clint_harris/ey3UD/

The cause of the problem starts when the form's loadRecord() function is called. This eventually results in setValue() being called for the checkbox group. If you look at src/form/field/Checkbox.js:355 you see that it uses CheckboxManager.getByName() to get all the checkboxes in the group, by name (in this examples, the name is 'roles'):

// File: src/form/field/Checkbox.js
initComponent: function(){
this.callParent(arguments);
this.getManager().add(this);
},

setValue: function(checked) {
var me = this;

// If an array of strings is passed, find all checkboxes in the group with the same name as this
// one and check all those whose inputValue is in the array, unchecking all the others. This is to
// facilitate setting values from Ext.form.Basic#setValues, but is not publicly documented as we
// don't want users depending on this behavior.
if (Ext.isArray(checked)) {
me.getManager().getByName(me.name).each(function(cb) {
cb.setValue(Ext.Array.contains(checked, cb.inputValue));
});
}
...

CheckboxManager (an unpublished singleton) is basically a MixedCollection with a few convenience functions:

Ext.define('Ext.form.CheckboxManager', {
extend: 'Ext.util.MixedCollection',
singleton: true,

getByName: function(name) {
return this.filterBy(function(item) {
return item.name == name;
});
},
...

The problem is that getByName() returns ALL checkboxes named 'roles'--even the ones from the OTHER form.

In other words, each time you set the values for a CheckboxGroup, you also set values for all other CheckboxGroups with the same checkbox names.

Does this seem like a bug to anyone else or am I not using the framework correctly?

charris
12 Oct 2011, 2:03 PM
Update: I've since figured out that, for one thing, the CheckboxGroup should be configured like this:


{
xtype: 'checkboxgroup',
fieldLabel: 'Actual Roles',
name: 'roles', // <--
columns: 1,
items: [
{ boxLabel: 'Role A', name: 'roleA' }, // <--
{ boxLabel: 'Role B', name: 'roleB' } // <--
]
}

NOT like the examples in the docs, which show it done like this:


{
xtype: 'checkboxgroup',
fieldLabel: 'Actual Roles',
columns: 1,
items: [
{ boxLabel: 'Role A', name: 'roles', inputValue:'roleA' },
{ boxLabel: 'Role B', name: 'roles', inputValue:'roleB' }
]
}

This doesn't fix the issue, but is probably a necessary step in the right direction. I suspect that the main cause is that my model's 'roles' field is an array instead of a string/int/float/bool/date.

Bob Wilson
20 Jun 2012, 2:39 AM
At the beginning, I was using YOUR syntax (which is more logical), but with it, I had troubles to ajax-load checkboxgroup from a json server-response.

The final solution for me was to stick to the documentation syntax, where each box item of the checkbox group has the same name. :-?

I think Sencha team should enhance the documentation about this topic, because a lot of people are trying to figure out how to have default values & to ajax-load multiple values in a checkboxgroup.

I offer hot coffee for the update.~o)