Using a CheckBox control as a list item renderer in Flex

by Peter deHaan on January 27, 2008

The following example will show you how you can use a CheckBox control as a custom item renderer in a List control in Flex.
I haven’t done a lot of testing yet, so if you have any tips/suggestions/improvements, please, share them in the comments.

Full code after the jump.

View MXML

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2008/01/27/using-a-checkbox-control-as-a-list-item-renderer-in-flex/ -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
        xmlns:vo="*"
        layout="horizontal"
        verticalAlign="middle"
        backgroundColor="white"
        creationComplete="init();">
 
    <mx:Script>
        <![CDATA[
            import mx.events.CollectionEvent;
            import mx.utils.ObjectUtil;
 
            private function init():void {
                arrColl.dispatchEvent(new CollectionEvent(CollectionEvent.COLLECTION_CHANGE));
            }
 
            private function arrColl_collectionChange(evt:CollectionEvent):void {
                try {
                    var tArr:Array = arrColl.source.filter(selectedOnly);
                    textArea.text = ObjectUtil.toString(tArr);
                    lbl.text = tArr.length.toString() + " item(s) selected";
                } catch (err:Error) {
                    // ignore.
                }
            }
 
            private function selectedOnly(item:ListItemValueObject, idx:uint, arr:Array):Boolean {
                return item.isSelected;
            }
        ]]>
    </mx:Script>
 
    <mx:Array id="arr">
        <vo:ListItemValueObject label="One" isSelected="true" />
        <vo:ListItemValueObject label="Two" isSelected="true" />
        <vo:ListItemValueObject label="Three" isSelected="true" />
        <vo:ListItemValueObject label="Four" isSelected="true" />
        <vo:ListItemValueObject label="Five" isSelected="false" />
        <vo:ListItemValueObject label="Six" isSelected="false" />
        <vo:ListItemValueObject label="Seven" isSelected="false" />
        <vo:ListItemValueObject label="Eight" isSelected="false" />
        <vo:ListItemValueObject label="Nine" isSelected="false" />
        <vo:ListItemValueObject label="Ten" isSelected="false" />
        <vo:ListItemValueObject label="Eleven" isSelected="false" />
        <vo:ListItemValueObject label="Twelve" isSelected="false" />
    </mx:Array>
 
    <mx:ArrayCollection id="arrColl"
            source="{arr}"
            collectionChange="arrColl_collectionChange(event);" />
 
    <mx:Panel id="panel"
            title="Items"
            status="{arrColl.length} total"
            styleName="opaquePanel">
        <mx:List id="list"
                dataProvider="{arrColl}"
                alternatingItemColors="[#EEEEEE, white]"
                width="150"
                rowCount="8">
            <mx:itemRenderer>
                <mx:Component>
                    <mx:CheckBox selectedField="isSelected"
                            change="onChange(event);">
                        <mx:Script>
                            <![CDATA[
                                private function onChange(evt:Event):void {
                                    data.isSelected = !data.isSelected;
                                }
                            ]]>
                        </mx:Script>
                    </mx:CheckBox>
                </mx:Component>
            </mx:itemRenderer>
        </mx:List>
        <mx:ControlBar horizontalAlign="right">
            <mx:Label id="lbl" />
        </mx:ControlBar>
    </mx:Panel>
 
    <mx:TextArea id="textArea"
            verticalScrollPolicy="on"
            width="100%"
            height="{panel.height}" />
 
</mx:Application>

View ListItemValueObject.as

/**
 * http://blog.flexexamples.com/2008/01/27/using-a-checkbox-control-as-a-list-item-renderer-in-flex/
 */
package {
    public class ListItemValueObject {
 
        [Bindable]
        public var label:String;
 
        [Bindable]
        public var isSelected:Boolean;
 
        public function ListItemValueObject() {
            super();
        }
    }
}

View source is enabled in the following example.

For lots more information on item renderers from somebody who knows what he’s talking about, check out Alex Harui’s excellent item renderer articles: “Thinking About Item Renderers” and “More Thinking About Item Renderers”.

{ 27 comments… read them below or add one }

Keith January 28, 2008 at 1:02 pm

I am attempting to build a filter that will add or remove items from a Datagrid. The two fields I would like to filter are categories and locations. I would like to filter the two fields with a checkbox for each field. Here is the example. A user selects a location which filters the categories available at that location, it also filters the Datagrid. The user then selects a category which filters the DataGrid. If the user removes the check mark, the filtered data is removed from the DataGrid. The filter also has the ability to display all items. Is it possible to use your code in the example above?

Reply

Jesse January 30, 2008 at 3:21 pm

Hi Keith,

The way I accomplish that is to dispatch a custom DoFilter event each time a checkbox is checked/unchecked.

The DoFilter event triggers 2 things. First, it updates a list of active filters (unchecked check boxes). Second, it calls myDataGrid.dataProvider.refresh().

The refresh() call triggers the dataprovider’s sort() and filterFunction() functions.

You’ll need to define the filterFunction for the dataProvider such that it looks through the list of active filters and returns true/false for each item appropriately.

Jesse

Reply

Nathanael Jones February 28, 2008 at 8:54 pm

I’m trying to figure out how to make a List box multi-select using check-boxes as well as the standard ctrl/shift shortcuts.

I’ve tried modifying the selectedItems collection and overriding ctrlKey during the capture stage of the mouse events. Neither seem to work right.

Any ideas?

Reply

Nathanael Jones February 29, 2008 at 9:48 am

Finally figured it out. I’ll try to post the code on http://nathanaeljones.com/ when I get a chance to fully document it.

I subclassed List (CheckList) and overrode the mouseDownHandler and mouseUpHandler functions, and changed the event.ctrlKey property when the mouse was over a checkbox (actually, I delegated the decision to the item renderer through mouseEventToItemRenderer(e); and a custom ICheckListRenderer interface.

I subclassed Checkbox (BlindCheckbox) and overrode clickHandler, leaving it blank (except for the stopImmedatePropogation command when disabled).

I added an event handler for each checkbox in the renderer (listData set function).
To get the parent list from the item renderer you use IDropInListItemRenderer and implement listData.

_parentList.addEventListener(ListEvent.CHANGE, function():void{
   chkSelected.selected = _parentList.isItemSelected(me.Data);
});
chkSelected.selected = _parentList.isItemSelected(me.Data);

Here’s how to translate mouse coordinates arbitrarily from any UI element event to local coordinates (Used by the item renderer to determine whether the checkbox was clicked. I give the user a larger click area).

var pt:Point = new Point(e.localX, e.localY);
 pt = DisplayObject(e.target).localToGlobal(pt);
pt = globalToLocal(pt);

Reply

Pratap March 9, 2008 at 11:40 pm

any idea how to write following code using ActionScript??

Thanks in Advance….Pratap

Reply

Vijay March 13, 2008 at 12:59 pm

Hello Friends,

I have used this Multi-Selected Checkbox, but finding it difficult to write a function which does Select-All or Deselects All.

Can anyone please supply/guide me with the code.

Appreciate the help.

Regards,
Vijay

Reply

Vijay Anand Mareddy March 8, 2010 at 12:06 pm
public function selectAll():void {
            var _arr:Array = [];
            for ( var i:int=0; i &lt; super.dataProvider.length; i++ ) {
                _arr.push(i);
                var item:Object = super.dataProvider[i] as Object;                    
                if(item.hasOwnProperty(selectedField)){                        
                    if( item[selectedField] == false){            
                        item[selectedField] = true;                    
                    }
                }//if
            }//for
            super.selectedIndices = _arr;
        }//selectAll
 
        public function deselectAll():void {
            for ( var j:int=0; j &lt; super.dataProvider.length; j++ ) {
                var item:Object = super.dataProvider[j] as Object;                    
                if(item.hasOwnProperty(selectedField)){                        
                    if(item[selectedField] == true){                                
                        item[selectedField] = false;                            
                    }
                }//                    
            }//for
            super.selectedIndices = [];            
        }//deselectAll

Reply

Nik April 8, 2008 at 9:16 am

thanks for the code – I used it to create a very long list of items and had some trouble with the events. It ends up picking up scroll events too and so checkboxes end up getting random states.

I fixed it with changing your onChange fn to;

private function onChange(evt:Event):void {
   data.isSelected = selected;
}

so that it used the new checkbox state rather than assuming a state change. Hopefully that wan’t a dumb thing to do (worked at least).

Nik

Reply

Bharathi June 25, 2008 at 12:51 pm

Hi ,
I am very new to Flex. I want to do the same thing with Checkbox but i need it to display horizontally , how can I do it?

Please help
Bharathi

Reply

RamMohan July 17, 2008 at 10:23 pm

I have used this Multi-Selected Checkbox, but i wants to display selected checkboxes and as well as which one is not selected checkboxes in jsp code one page to another page .

Can anyone please supply/guide me with the code.

Reply

RamMohan July 17, 2008 at 10:25 pm

I have used this Multi-Selected Checkbox, but i wants to display selected checkboxes and as well as which one is not selected checkboxes in jsp code one page to another page .

Can anyone please supply/guide me with the code.

* Select the checkbox for those students who are present, for absentees do not select.

Student Name
Leave Applications

pavan pavan
-

Prasad Rao-

Ramesh Shrestha
-

satish india-

star starworld-

Vikas Verma-

 

 

Reply

D.A. October 24, 2008 at 4:56 am

How can i change this example if data provider is XML content?

Reply

vijay November 4, 2008 at 2:52 am

really its very nice example of my work

thank you,
vjn

Reply

Kirti January 3, 2009 at 4:28 am

I want to use this list box in my application but dataprovider for my list is an arraycollection of class Assets type. I am using RemoteObject to call data from server

package
{
	[Bindable]
   [RemoteClass(alias="vs.Asset")]
	public class Asset
	{
		public function Asset()
		{
		}
		public var assetId:Number;
      	public var assetName:String;
      	public var company:String;
      	public var categoryId:Number;
        public var modelNo:String;
        public var unitPrice:Number;
      	public var serialNo:String;
      	public var purchaseDate:String;
      	public var isMovable:Number;
	}
}

But this doesn’t work, tell me where i am going wrong ?

Reply

David January 7, 2009 at 6:47 am

Hi Peter,

You use the filter method on the underlying array (source) for the
arrayCollection datasource of the list. The function is:

private function selectedOnly(item:ListItemValueObject, idx:uint, arr:Array):Boolean {
    return item.isSelected;
}

The filter method, according to the Flex docs, ‘executes a test
function on each item in the array and constructs a new array for all
items that return true for the specified function.’ That I understand,
and I can see that you’re being returned an array, tArr. But how are
you able to call a function with that signature and know that all
three parameters are going to be passed in? I tried adding a fourth
parameter – , porky:String – and it broke. How does this method know
that idx:uint is OK, but porky:String isn’t?

I also tried adding this to the arrColl_collectionChange function:

if(list.selectedIndex == -1)
{
    Alert.show("No items are selected!");
}

But the only time it fires is when the app first loads, presumably
because the list isn’t yet populated. If I uncheck all the checkboxes,
it doesn’t show. The event in question is the change event of the
checkbox, so it seems to me this ought to work. No?

I did get it to work by modifying as follows:

if(!tArr.length)
{
    Alert.show("No items are selected!");
}

Reply

Sudheer January 10, 2009 at 4:11 am

Hi
I have a problem with checkbox with combobox
when ever i click on label or checkbox it’s selecting
BUT
when i click on list item (NOT ON LABEL OF LIST) its not selecting

Can any one give solution

Reply

Keith H. January 24, 2009 at 4:46 am

Hi Peter,

Thanks for the tutorial. Do you know if it’s possible to do the same thing, but using a more complex ItemRenderer which includes a CheckBox? For example:

<mx:itemRenderer>
    <mx:Component>
        <mx:HBox horizontalAlign="left" paddingLeft="5">
            <mx:Script>
            <![CDATA[
                [Bindable]
                public var cbSelected:Boolean;
            ]]>
            </mx:Script>

            <mx:CheckBox id="displayCheckBox" selected="true" click="cbSelected = displayCheckBox.selected;" />
            <mx:Label text="{data.color}" />
        </mx:HBox>
    </mx:Component>
</mx:itemRenderer>

I’ve been trying to do this by binding a variable in the item renderer’s outermost component which is tied to the underlying variable in the ArrayCollection I want to change, however, if I call a function right after setting the linked variable, the underlying ArrayCollection will not have been updated yet. If I call the same function manually a second later though, it will have.

I also tried listening for the “CollectionEvent.COLLECTION_CHANGE” event at the ArrayCollection level, but once again, the changes do not take effect soon enough with the indirect binding.

Any suggestions?

Reply

PK April 8, 2009 at 3:39 pm

Hi Peter
I like your solution of generating the CheckBox using ItemRenderer at run time but if I have to disable the checkbox then how can I achive that using ItemRenderer, I tried by giving enabled=”false” but this does not work.

Thanks,
PK

Reply

Daniel May 9, 2010 at 7:50 pm

Hi PK,
Did you found a solution to uncheck the checkbox in te datagrid by code. If I remove the Item the checkbox are still checked and do weird things.

Reply

Steve October 9, 2009 at 7:15 pm

Hi Alex, thanks for the great example.

Just a simple question: In your array declaration, you have, for each element:

vo:ListItemValueObject

But the in the ListItemValueObject.as file, there is just “package”, not “package vo”. Just curious about this little part. I’m a Flash/Flex newb by the way.

Steve

Reply

Steve October 9, 2009 at 7:16 pm

Meant “Peter”, not “Alex”. Not sure where I got that from.

Reply

Steve October 9, 2009 at 7:18 pm

Crap, those are two different things, namespaces and packages, nevermind.

Reply

MXPain November 19, 2009 at 3:21 pm

Thank, very useful tutorial)

Reply

Dishanka December 7, 2009 at 2:41 am

well example bro. This is the example which is what i wanted. Thanks so much

Reply

KevM January 13, 2010 at 3:53 am

How do I change it so the i’m using an XML as the dataprovider rather than the array collection?
Thanks

Reply

Daniel May 9, 2010 at 7:55 pm

What about if I want to have a “Unckeck All” button?? How do I uncheck the comboboxes? How do I enter in the ItemRenderer>Componente to uncheck it?

Reply

Senling July 28, 2010 at 7:04 am

I just having the arraycollection to be listed in checkbox.

Anti-Spam Protection by WP-SpamFree

Previous post:

Next post: