PDA

View Full Version : Help with Dynamic Checkboxes



JustaCoder
9 May 2013, 12:59 PM
Hello,

Coder of 17 years but new to Ext.js. Basically I am lost with it. Working on an issue in a component installed in Modx admin with Ext version 3.4.0. For this reason many of the code samples out there, including the Sencha checkboxgroup samples, aren't working. Please assume I've been over the documentation as well as a few hundred other resources trying to solve this **simple** task:

The task:

A "company" has "workers" and the workers may work at multiple locations. When the worker edit window loads, it queries a php script that indeed returns a valid JSON string with the company's locations. I simply cannot get the data into checkboxes that render in the form.

What DOES (sorta) work: This is a combo box that does populate the locations, but for whatever reason, multiSelect does NOT work (probably something deep in the modx code disabling it: )



ThisComponent.combo.Locations = function(config) {
config = config || {};
Ext.applyIf(config,{
name: 'locations'
,hiddenName: 'locations'
,displayField: 'name'
,valueField: 'id'
,multiSelect: true
,fields: ['id','name']
,url: ThisComponent.config.connectorUrl
,baseParams: {
action: "mgr/locations/getCheckboxList"
,practice: ThisComponent.request.practice
}
});
ThisComponent.combo.Locations.superclass.constructor.call(this,config);
};
Ext.extend(ThisComponent.combo.Locations,MODx.combo.ComboBox);
Ext.reg('this-component-combo-locations',ThisComponent.combo.Locations);


If multiSelect worked as it should, we could use this, but it doesn't. On to checkboxes.

There is a master .js in the component that defines the objects, here is what I've come up with gathered from various sources:



var LocationsItems = [];
Ext.namespace("Ext.checkboxgroup");
Ext.checkboxgroup.RemoteCheckboxGroup = function(config) {
config = config || {};

var resourceStore = new Ext.data.JsonStore({
fieldValue: 'id'
,fields: ["id", "name"]
,autoLoad: true
,root: "results"
,url: ThisComponent.config.connectorUrl
,baseParams: {
action: "mgr/locations/getCheckboxList"
,practice: ThisComponent.request.companyid
}
,listeners: {
load: function(results) {
for(var i = 0; i < records.length; i++) {
LocationsItems.push({id: records[i].data.id, boxLabel: records[i].data.name});
}
}
}
,items:LocationsItems
});
resourceStore.load();
Ext.checkboxgroup.RemoteCheckboxGroup.superclass.constructor.call(this, config);
};
Ext.extend(Ext.checkboxgroup.RemoteCheckboxGroup,Ext.form.CheckboxGroup);
Ext.reg('this-component-checkboxgroup-locations',Ext.checkboxgroup.RemoteCheckboxGroup);


And my window, which otherwise works fine:



PD.window.UpdateWorker = function(config) {

this.ident = config.ident || 'this-component-window-du';
Ext.applyIf(config,{
id: this.ident
,width: 500
,title: 'Update Worker'
,url: ThisComponent.config.connectorUrl
,action: 'mgr/workers/update'
,fields: [{
xtype: 'hidden'
,name: 'id'
,value: true
},{
xtype: 'this-component-checkboxgroup-locations'
,fieldLabel: 'Locations'
},{
// For the combo list that doesn't work as multiselect
/* },{
xtype: 'this-component-combo-locations'
,fieldLabel: 'Locations (Hold CRTL to select multiple locations)'
,fieldValue: 'id'
,width: 300
},{*/
fieldLabel: 'First Name'
,name: 'first_name'
,xtype: 'textfield'
,width: 300
,allowBlank: false
},{
fieldLabel: 'Last Name'
,name: 'last_name'
,xtype: 'textfield'
,width: 300
,allowBlank: false
},{
fieldLabel: 'Specialty'
,name: 'specialty'
,xtype: 'this-component-combo-fullspecialty'
,width: 300
,allowBlank: false
}]
});
ThisComponent.window.UpdateWorker.superclass.constructor.call(this,config);
};


What can I do here to get the checkboxes in the form window?

mitchellsimoens
13 May 2013, 7:46 AM
So you are just pushing items to the LocationsItems array and expecting it to know about this? That's not really how JavaScript works. Instead of pushing the items to the LocationsItems array, create an array and use the add method on the checkbox group and doLayout. Here is a little example of what I mean:


var form = new Ext.form.FormPanel({
renderTo : document.body,
title : 'Test',
items : [
{
xtype : 'checkboxgroup',
fieldLabel : 'Foo',
items : [
{
boxLabel : 'One'
},
{
boxLabel : 'Two'
}
]
},
{
xtype : 'button',
text : 'Add Items',
handler : function() {
var group = form.getComponent(0),
panel = group.panel,
items = [],
i = 0,
length = 5;

for (; i < length; i++) {
items.push({
xtype : 'checkbox',
boxLabel : 'Checkbox ' + i
});
}

panel.removeAll();
panel.add(items);
panel.doLayout();
}
}
]
});

JustaCoder
13 May 2013, 8:07 AM
Thank you - yes I knew it had something to do with scope of "LocationItems" but I've tried many things and none of them seemed to work. Thank you again and I'll give this a try!

JustaCoder
14 May 2013, 8:47 AM
Busy day yesterday, I've re-visited this project and had a look.

The problem is not that I'm pushing items to the LocationsItems array - the data never gets there. If it did, it might even work. :-) In fact, in one interation I had named it "items" and it's still empty/null.

See my "working" but not working example. This indeed returns the JSON containing the data:



,baseParams: {
action: "mgr/locations/getCheckboxList"
,practice: ThisComponent.request.companyid
}


But it never gets here:



,listeners: {
load: function(results) {
for(var i = 0; i < records.length; i++) {
LocationsItems.push({id: records[i].data.id, boxLabel: records[i].data.name});
}
}
}
,items:LocationsItems


results is undefined, records is undefined, it's like "listeners" has no effect.

I need to understand what's happening there, and don't. :-\ Thank you for your patience with the EXT newb.

willigogs
14 May 2013, 9:14 AM
The issue is that your locationItems array is empty when the store is initialized - and even though you may update this array later - that doesn't update the items in the store. You would have to tell the store to reload this array again once you've populated it...

JustaCoder
14 May 2013, 9:30 AM
Thank you - here's a new version, I took another look at a combo box that is working. Firebug error is "this.items is undefined" in ext-all.js.



Ext.namespace("Ext.checkboxgroup");
Ext.checkboxgroup.RemoteCheckboxGroup = function(config,getStore) {
config = config || {};

Ext.applyIf(config,{
fieldValue: 'id'
,fields: ["id", "name"]
});
Ext.applyIf(config,{
store: new Ext.data.JsonStore({
url: ThisComponent.config.connectorUrl
,autoLoad: true
,root: "results"
,totalProperty: 'total'
,errorReader: MODx.util.JSONReader
,remoteSort: config.remoteSort || false
,autoDestroy: true
,baseParams: {
action: "mgr/locations/getCheckboxList"
,companyid: ThisComponent.request.companyid
}
,listeners: {
load: function(results) {
for(var i = 0; i < records.length; i++) {
items.push({id: records[i].data.id, boxLabel: records[i].data.name});
}
}
}
})
});
if (getStore === true) {
config.store.load();
return config.store;
}
Ext.checkboxgroup.RemoteCheckboxGroup.superclass.constructor.call(this,config);
this.config = config;
return this;
};
Ext.extend(Ext.checkboxgroup.RemoteCheckboxGroup,Ext.form.CheckboxGroup);
Ext.reg('pd-checkboxgroup-locations',Ext.checkboxgroup.RemoteCheckboxGroup);


The json returned as reported by Firebug (I can see I have an issue with the PHP at companyid, I just need to get this data into the window!)

{"total":"3","results":[{"id":83,"companyid":0,"name":"new name","url":"","address":"","address2":"","city":"","state":"","zip":"","telephone":""},{"id":82,"companyid":0,"name":"steve test 2","url":"","address":"","address2":"","city":"","state":"","zip":"","telephone":""},{"id":81,"companyid":0,"name":"steve test 3-17-13","url":"","address":"","address2":"","city":"","state":"","zip":"","telephone":""}]}

JustaCoder
17 May 2013, 10:12 AM
Can someone please help with this. All we need to do is get the JSON into the items array. We will gladly pay to solve this one thing.

JustaCoder
17 May 2013, 10:50 AM
I've almost got it! The below code now dumps "items" in the console, items is populating, but still getting "this.items[0] is undefined" in ext.all.js. I just need one little push, anyone see it?

The difference was adding the fields to the first config block.



Ext.namespace("Ext.checkboxgroup");
Ext.checkboxgroup.RemoteCheckboxGroup = function(config,getStore) {
config = config || {};

Ext.applyIf(config,{
fieldValue: 'id'
,fields: ["id", "name"]
,items: []
});
Ext.applyIf(config,{
store: new Ext.data.JsonStore({
url: ThisComponent.config.connectorUrl
,autoLoad: true
,root: "results"
,totalProperty: 'total'
,fields: config.fields
,errorReader: MODx.util.JSONReader
,remoteSort: config.remoteSort || false
,autoDestroy: true
,baseParams: {
action: "mgr/locations/getCheckboxList"
,practice: ThisComponent.request.companyid
}
,listeners: {
load: function(t, records, options) {
items = [];
for(var i = 0; i < records.length; i++) {
items.push({id: records[i].data.id, boxLabel: records[i].data.name});
}
console.log(items);
}
}
})
});
if (getStore === true) {
config.store.load();
return config.store;
}
Ext.checkboxgroup.RemoteCheckboxGroup.superclass.constructor.call(this,config,getStore);
this.config = config;
return this;
};
Ext.extend(Ext.checkboxgroup.RemoteCheckboxGroup,Ext.form.CheckboxGroup);
Ext.reg('this-component-checkboxgroup-locations',Ext.checkboxgroup.RemoteCheckboxGroup);

JustaCoder
17 May 2013, 11:21 AM
I think I see it (doh.) items is only within the scope of the function in listeners->load. Close? How do I return it to the parent object?