CheckBox selection in DataGrid and List
Several folks have asked how to use Checkbox renderers to handle multiple selection in a DataGrid or List. There are some solutions out there already, but here's mine. Usual caveats apply.
« Flex and ScaleMode | Main | Smooth Scrolling List »
Several folks have asked how to use Checkbox renderers to handle multiple selection in a DataGrid or List. There are some solutions out there already, but here's mine. Usual caveats apply.
Comments
Do you have any suggestions for how to maintain the "selected" style you usually get with selected items in a list, the hightlight, etc? I posted a solution to this on my blog, but it's a hack at best. I think the ListBase is hardcoded to look for a CTRL or SHIFT modifier so I intercept mouse events and set those properties.
http://www.thegoldhold.com/?p=4
I'd love to hear your thoughts on a 'cleaner' approach, but that's what I had to do to get the job done.
Thanks for your thoughts as always.
-------------------
Alex responds:
In my example, I override drawSelectionIndicator to turn off the visuals. If you remove that override, you should see the items show selection as they are checked.
The basic principle of my example is to essentially make "dead" checkboxes. They don't handle mouse or key events at all and just let the List or DataGrid handle the clicks as if it was a regular renderer, except I force the control to think that the ctrl key is pressed all the time.
It sounds like you took a similar approach. I glanced at your code briefly and saw that there was some room for optimization so went ahead and posted mine.
Posted by: Danny Gold | February 29, 2008 5:50 PM
Good stuff. I updated my example to override the selectItem function as well. Glad you posted your approach so I can make those changes in our project as I find myself using the checkboxes for most of our datagrids. Great to have such an active community to build on.
Posted by: Danny Gold | February 29, 2008 10:55 PM
The following happens when reordering the columns in the grid:
TypeError: Error #1034: Typumwandlung fehlgeschlagen: mx.controls.dataGridClasses::DataGridItemRenderer@2de8cf11 kann nicht in mx.controls.CheckBox umgewandelt werden.
at CheckBoxDataGrid/drawItem()
at mx.controls.dataGridClasses::DataGridBase/drawVisibleItem()
at mx.controls.dataGridClasses::DataGridBase/makeRows()
at mx.controls.dataGridClasses::DataGridBase/makeRowsAndColumns()
at mx.controls::DataGrid/makeRowsAndColumns()
at mx.controls.listClasses::ListBase/makeRowsAndColumnsWithExtraRows()
at mx.controls.listClasses::ListBase/updateDisplayList()
at mx.controls.dataGridClasses::DataGridBase/updateDisplayList()
at mx.controls::DataGrid/updateDisplayList()
at mx.controls.listClasses::ListBase/validateDisplayList()
at mx.managers::LayoutManager/validateDisplayList()
at mx.managers::LayoutManager/doPhasedInstantiation()
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/callLaterDispatcher2()
at mx.core::UIComponent/callLaterDispatcher()
-------------------------
Alex responds:
Like I said, caveats apply. I would set draggable=false on the column so it stays as the first column.
Posted by: Michael | March 1, 2008 3:37 AM
Hi. This is very useful if the list is used "alone". I have a somehow different situation.
The data provider is to be changed externally (by a filter function), when the user writes in a textbox (shown items have the typed string as a substring). On the other side, the 'checked' state of the box must persist whether or not the item are filtered out, so using internal 'selectedItems' is out of question, because when items are filtered out they are of course automatically deselected.
Using just a custom function for selection with inthe checkBox renderer gives the 'show' part, but the 'change' part is much harder. Do you have any idea? If I just use the renderer as editor, the diplays shows garbage in the renderers...
Typically the list of 'checked' items lives in an ArrayCollection somewhere in the component.
-----------------------------
Alex responds:
I should have mentioned the limitations of this version. It doesn't allow the kind of functionality you are looking for nor does it allow sorting by selected entries. Both require storing some knowledge of the selection state in the dataProvider.
If you have a slot in your dataobjects to store selection state, great, and then I might not use the List's selection code at all.
If you don't have a slot for your dataobjects, you'll need a separate collection. One of these days, maybe I'll show how to do a mergedCollection. I thought Deepa was going to post an example, but I didn't see it on her blog.
Posted by: saverio | March 3, 2008 2:04 AM
Hi. This has worked great for me but I have been trying to work out how to have all the check boxes defaulted to selected.
I've tried a couple of things but can't get it to work.
Can you suggested a solution ?
-----------------------
Alex responds:
I would just create an array of numbers from 0 to n and pass that into selectedIndices.
Posted by: Aymsley Edwards | March 18, 2008 3:09 AM
Hi Alex,
I have a question regarding the selection of a checkbox within the datagrid by default. As in, I am trying to get a checkbox to be checked by default using a dataprovider. I have an array with one of the elements as { source: "WH", repCost: "10.99", sourceableQuantity: "35", totalQuantity: "20", leadTime: "15", relevant: true}. I convert this Array to an ArrayCollection and pass this as a dataprovider to CheckBoxDataGrid. I have dataField="relevant" editorDataField="selected" rendererIsEditor="true"
width="20" sortable="false" editable="true" itemRenderer="controls.itemRenderers.CheckBoxRenderer" for the checkbox DataGridColumn. However, it doesnt display the checkbox as checked. What am I doing wrong?. Sorry if this is a noob question. Thanks for all your help.
--------------------
Alex responds:
You might be better off using this post:
http://blogs.adobe.com/aharui/2008/03/custom_ilists_checkboxdatagrid_1.html
Posted by: Vinay | March 19, 2008 12:20 PM
thank you for this code.. appreciate it .. saved me a load of time.. :)
btw. rite now jus tryin to figure out and change it.. why do you have a checkbox selection on keyboard press.. i mean when you keypress 'S', 'I' or any character it selects the particular item in the list box. I jus want to get it into focus but selection only by mouse click..
i'll try to figure it would will shout fr help if required.. :)
--------------
Alex responds:
I didn't set up that functionality, it is built into the list classes. They search for entries based on the last letter typed and selected them. You can turn that off by overriding the findString() method and have it do nothing.
Posted by: Varun Shetty | March 24, 2008 2:26 PM
Hi, It is really a great knowledge source all the samples you write. Thanks for all the help and greetings from México.
My question, once, I have this array of index, how can I send them all to a PHP, I'll take care the php part but what about the flex part, I would like to send not the index but the names so I can receive them with a php function and then submit them to a database, I would like to use it like a shopping cart selector.
--------------------
Alex responds:
If you are using this example, I would get the selectedItems array from the DataGrid. It will be an array of references to items in the dataprovider, and you can pull the appropriate fields and post them back to your server.
Posted by: Edward | April 16, 2008 7:39 PM
I dont understand the code, but I can tell you this has been a life saver. Thank you
Posted by: Atro | May 12, 2008 10:00 AM
Thanks for example. But you had some mistake in using sorting: number of selected lines defining uncorrectly.
------------------------------
Alex responds:
OK, thanks.
Posted by: Dmitriy | May 16, 2008 9:24 AM
Hi Alex,
Thanks for this code .
I have a question regarding the editing of other editable dataFields .
if i use an itemEditor in dataGrid and try to select
it to change it's value , the checkBox column will be selected as well .
is there any property .. to restrict selectItem function to fire only on checkbox column ?
I was playing with this line
--
return super.selectItem(item, false, true, transition);
---
but no luck to tell datagrid , that is not a checkbox .
you mentiend using if (item is CheckBox) but still same thing .
I retrieved my Data from Coldfusion and everything else works .
I really appreciate for your help .
Thank you.
Posted by: Max | May 20, 2008 5:40 PM
OpenFlux е Degrafa най-добър приятел. Чудите се как започваш да се направят всички тези готини собствени виждания за вашата OpenFlux компоненти? Yup, тези две бяха така означаваше, че една OpenFlux идва с Degrafa печени в. Помислете си напълно, което има право да направи хората призива Ви получер lier-различно, когато им каже, че наистина е Flex ап. Това е начин извън стайлинг, начин, след одиране, че е искал ние stole, че някои от бъдещите версия на Flex или нещо
Thanks ..
----------------
Alex responds:
You're welcome. I wish I knew for what...
Posted by: دردشة | June 7, 2008 10:48 PM
I have a quick question...I'm very new to Flex, and I was wondering how to adjust your code to display a CheckBoxList for an array of strings instead of an array of objects. Thanks for your time.
------------------
Alex responds:
I think you can just use an array of strings. If it doesn't work, ask on FlexCoders for help.
Posted by: Chris | June 16, 2008 9:09 AM
I have a simple question, hope someone can help me.
I have a regular datagrid, one of the column is checkbox, another column is editable. My requirement is that when the checkbox is checked/selected, I want to clear the editable column. I was able to change the data(array collection) behind the datagrid, but the UI is not refreshed. How to refresh the UI inside a customized itemrender?
thanks
-------------------
Alex responds:
You might have to call itemUpdated. If you have further questions, try posting on FlexCoders
Posted by: chenfang zou | July 3, 2008 2:32 AM
I'm very new to flex. I would like to add a comboxbox that controls the selection in the datagrid. I have "All" and "None" in my combobox and if I select "All", it should checkmark all the checkboxes in the datagrid. Do you have any suggestions? Thanks for your time
---------------------------
Alex responds:
I would make an array of numbers from 0 to length-1 and set that as selectedIndices if you want to select all
Posted by: Francis | July 9, 2008 12:16 PM
thanks for the code
it's realy helpful
Posted by: jbr | July 18, 2008 4:31 PM
Hi Alex,
Thanks for your code. I want checkbox column as the last one in datagrid.Then that case its giving error like TypeError: Error #1034: Type Coercion failed: cannot convert mx.controls.dataGridClasses::DataGridItemRenderer@44115b1 to mx.controls.CheckBox
Could you suggest any solution?
-------------------
Alex responds:
Depends on the rest of the stack trace. Somebody's code is expecting a checkbox but getting a regular cell.
You'll get faster response if you ask on FlexCoders
Posted by: Kavitha | August 28, 2008 3:37 AM
Hi Alex,
Thanks for the code. It saves lot of time for a new bee like me.I have a question. I want to disable some of the checkboxes based on one filed in my data grid. For this one, I wrote teh necessary logic in updatedisplaylist() of checkboxrenderer.as. Sample code is given below.
if(!( ci sTextField)){
if(so and so){
this.enabled=false;
this.selected=false;
}else{
this.enabled=true;
}
}
This one is giving random results when I scroll the datagrid. If I dont scroll everything is working as expected.
Please advice me in fixing this.
Thanks,
vsr.
-------------------------
Alex responds:
See the other item renderer posts. Renderers get recycled and need to be completely data-driven.
Posted by: sudha | September 2, 2008 7:29 AM
hi Alex thx for your code,
help me do this in Flash using AS3? thx very much...
------------------------
Alex responds:
Sorry, I don't have the time for that
Posted by: Agil | September 22, 2008 3:04 AM
Hi,
I'm trying to get your code working in a fully AS-written Flex application, so I use no mxml files, only AS.
If I use ...
dgCol.itemRenderer = CheckBoxRenderer;
I get an error that CheckBoxRenderer is not a ClassFactory. If I try ...
dgCol.itemRenderer = new ClassFactory(CheckBoxItemRenderer);
It compiles, but the CheckBoxes don't show up. How is this done correctly in AS3 only? The docs mostly have only mxml source examples either so they are not much of a help.
Thanks for any tips!
--------------------
Alex responds:
Not sure what you mean by AS3-only, but it sounds like the default Styles are not compiled in, which MXMLC takes care of.
Posted by: sascha/hdrs | October 14, 2008 1:30 AM
Hi Alex,
i am using item renderer checkbox and headerer renderer check box for select/deselect of all the datagrid rows but when i move the vertical scroll bar up and down . i am not able to retain the checked status . it is in consistent when i use scroll. pls help me to over ride this issue .
thanks in advance
ashok
-------------------------
Alex responds:
It depends on how you store the selected state and how the item renderers refreshes the checked status. Look more closely at my examples.
Posted by: Ashok | October 22, 2008 6:20 AM
Hi Alex,
first of all thanks for your component, I found it very useful for my needs.
Unfortunately, when I'm using the arrow keys UP & DOWN, and the Page UP & DOWN when the datagrid got the focus, the checkboxes are un/selected.
Can you help me to avoid this behaviour? I tried your suggestion to Vinay ( override findString() ) but it doesn't work.
Cheers,
Andrea
------------------------
Alex responds:
I don't think you want it to change the checkboxes as you use UP and DOWN. It wouldn't give you any control over doing disjointed selection sets. The way the code works now is that you hit space bar to toggle the checkbox.
Posted by: Andrea | October 31, 2008 11:38 AM
Just curious, is it by design that none of your demos run in IE7? (XP SP3)
-----------------
Alex responds:
I think IE7 has security that prevents hitting a link to a SWF. I don't use it so I don't know if there's a solution to just hitting a SWF link. If our blog software made it easier to upload files, then I'd upload the html and js wrappers that would get it to work.
Posted by: JMP | November 27, 2008 4:07 AM
Hi Alex,
Thanks for you work here, as many mention, it's much appreciated.
One quick query re:
A dg with multiple columns & rows of Check Boxes.
Select ONE check box.
Scroll (horizontally or vertically) would cause all check boxes on the row to become selected?
BTW it is using your example simply adding on an extra column (few minor tweaks).
Cheers,
Simon
--------------------
Alex responds:
This example binds the checkbox's selection state to whether the row is selected or not. If you didn't wire it up your version properly, it may not be updating correctly. When you select one checkbox on a row, the others on the row should have become selected right away, and not just after scrolling.
Posted by: Simon Bailey | December 16, 2008 5:32 AM
One stupid question, how can I get the selectedItems firstName in one variable?
---------------------
Alex responds:
I'm not sure I understand the question. You'll get an array of selectedItems and then have to iterate through the array. You can append all of the firstNames into a single string if you want.
Posted by: Dimitar | December 17, 2008 8:41 AM
Thanks for the response Alex. Yes it will select them all on click, I implemented some logic to identify the column to try and prevent this happening (data.column = listData.columnIndex). However, on scroll this logic goes down the pan, so how would I ensure that the selected value is bound to the individual column and row and not the whole row and column?
-------------------------
Alex responds:
The checkbox selection must be driven from some selection model or the data. For example, if you've added a selectedColumn property then each checkbox should test against that.
Posted by: Simon Bailey | December 29, 2008 8:45 AM
I have documented my approach for creating a reusable checkbox header renderer along with the sort functionality here...along with the source code as well :)
http://expresscode.wordpress.com/2008/12/05/reusable-custom-headerrenderer-for-advanceddatagrid-control/
I have used the approach of programming to an interface and a small work around to preserve the sort functionality
Posted by: Pavan | December 29, 2008 10:00 AM
Hey Alex,
Very cool example. I am having a problem figuring out how to delete all the selected items in the List control. I gave up on trying to incorporate the checkboxes so I went basic and just had a list with several items. There seems to be a bug with deleting each selected item. I've tried several different methods and RemoveItem isn't working (don't think I can use removeItemAt because the list's index count will change as each item is deleted). Any ideas? Sorry, this may be off-topic.
--------------------------------
Alex responds:
Ask on FlexCoders if you haven't already, but an array of indices should do the trick. It might be more efficient if the array is in reverse order
Posted by: Scott | January 9, 2009 5:20 PM
Alex,
Thanks a lot for the code.
This seems to working fine but how do i select objects or rows which are selected in a Grid?
Here is my case:
I have DatGrid with dataProvider as List of custom objects. I want to give the user an option on selecting objects with a checkbox in first column (which is not tied to any property in Object) and on Select/De-select it shows indices of all the Objects. But when i sort these indices get re-calculated. At the end i need to get all the objects which are user selected?
Any idea how to do this?
--------------------
Alex responds:
Not sure I understand. Are you saying that the list of selected indices is invalid after a sort? I would use selectedItems instead of selectedIndices. SelectedItems should still be valid after a sort.
Posted by: Sree | April 6, 2009 3:48 PM
DataGrid with selection by checkboxes
http://blog.enginer.org.ua/2009/05/checkboxselectiondatagrid.html
Posted by: enginer | May 23, 2009 3:45 AM