Open Source Flex Components: AdvancedList and CheckBoxList

The ZoomFrame component for Flex that I released last month got some good buzz. Today, I’m ready to release two more Flex components. Both are simple, but useful. The AdvancedList component adds a bit of functionality to the basic List. The CheckBoxList component adds a special item renderer with a CheckBox, and its selection changes hook into the standard List selection system. Have a look at the demo of AdvancedList and the demo for CheckBoxList to get an idea of how each works.

Screenshot of AdvancedList Component Example

The AdvancedList adds two nice things. First, you have the ability to disable specific items in the List through the data provider. They won’t be selectable through user interaction. This is achieved through the enabledField and enabledFunction properties. They work very much like the standard labelField and labelFunction properties. Additionally, AdvancedList gives you more control over drag-and-drop operations. By default, items that are dragged from a List get the drag format type “items” and any List will accept these items if dropEnabled is set to true. However, what if you have several List on screen, all are able to accept dropped items, but you want to restrict drag-and-drop between certain specific Lists? With the ability to change the dragFormat from “items” to something more specific like “shoppingCartItems”, you have more options and control.

Screenshot of CheckBoxList Component Example

CheckBoxList, as I mentioned, creates a List where selected items are shown with CheckBoxes. Multiple selection is enabled by default, and pressing the Ctrl key is not required. This component has a couple advantages. First, a collection of related CheckBoxes is now enclosed in a scrolling List. This saves on space, and we all know many apps need all the extra space they can get. Plus, the frame helps to visually associate the CheckBoxes as a set. Secondly, this component can replace a regular multi-select list. If you’ve ever seen a web form where one of these lists is used, you’ll know that they must always have instructions to tell you to press the Ctrl or Command key to select multiple items. That’s barely usable. In fact, I’d be afraid to watch my grandma if she had to enter data into that form. Instead, the CheckBoxList offers a familiar concept, standard CheckBoxes, and it puts them within another familiar concept, a scrolling List. No instructions needed.

Of course, just like the ZoomFrame component, the source code for the AdvancedList and CheckBoxList components are available under the terms of an MIT-style license. Please feel free to use them in both commercial and open source projects. There are a few other components I intend to release after some polishing, so be sure to check back soon.

About Josh Tynjala

Josh Tynjala is a frontend developer, open source contributor, bowler hat enthusiast, and karaoke addict. You might be familiar with his project, Feathers UI, an open source user interface library for Starling Framework that is included in the Adobe Gaming SDK.

Discussion

  1. BOb

    You have a little bug …

    The disabled line 3 is selectable if you click on line one and then shift click the last one. Number three also selected

    HTH

    BOb

  2. Josh Tynjala

    Erik, I haven’t looked very deeply into the ComboBox code, but I imagine that it wouldn’t be too difficult to make use of the AdvancedList (or at least some of its code) to give the ComboBox similar enhancements.

  3. Pingback: Just Flashing - Today’s Top Blog Posts on Flash - Powered by SocialRank

  4. Pingback: All Night Coder - Today’s Top Blog Posts on Programming - Powered by SocialRank

  5. Nico

    Hello,

    I was also looking for a Combobox that can disable items. To achive this, I only had to use AdvancedList as dropdownFactory in my custom Combobox. Very nice, thanks a lot Josh!

  6. Christopher Wigginton

    Nice Job.

    I needed the ability to pre-select the items using the dataProvider. So I added the following to your CheckBoxList. It checks for a “selected” key in the dataProvider array. Worked like a champ. I’m Still not sure if the validateNow() should be placed before setting the dataProvider or after.

    override public function set dataProvider(value:Object):void
    {
    	this.validateNow();
    
    	super.dataProvider = value;
    
    	var selectedArray:Array = [ ];
    
    	for ( var i:int=0; i < value.length; i++ ) {
    		if(value[i].selected)
    			selectedArray.push(i);
    	}
    
    	super.selectedIndices = selectedArray;
    }
  7. David

    Without wanting to appear totally stupid..I have downloaded the source code but don’t know where to place them to use the advanced list eg where does the com. file go?

  8. Josh Tynjala

    David, you can put them directly in your project next to the main MXML application file, or you can put them anywhere and add the containing folder to the Build path in your project’s properties.

  9. Peter

    Hi,

    Great component, but it seems the measure() method in the CheckBoxListItemRenderer fails when I do not set a explicit width to the CheckBoxList control. This results in a CheckBoxList control of 4 pixels wide.

    Is this an error, or do I do something wrong ?

    Thanks,
    Peter

  10. Bob

    Thanks so much, Josh — I, too, found this to be exactly what I needed for disabling items in a combobox. Excellent component!

  11. Shikha

    Thats Great, i just wanted a plugin sort of stuff for my already existing app and it works wonderful.

    Thanks

  12. David

    When I apply an itemrenderer to the list it is not obvious that a list item is disabled until you give it focus with the cursor. Is there a way around this?

  13. SD

    I just downloaded the source for the checkbox list. There is no doubt you have saved me a couple of hours of dev time. I owe you a beer 🙂

  14. Pingback: Disable item in Combobox | Ajay Chhaya

  15. Ian Marett

    Great component, saved me a lot of working out. One question though, the textRollOverColor doesn’t seem to be working, is there a trick to getting this to work?

  16. Niko

    Hey really cool Components.
    Exactly what I needed! Thx

    But i have a question;
    Is there a posibilty to make the checkbox list poping up, like the combobox list?

  17. Josh Tynjala

    Niko,

    Check out the dropdownFactory property on ComboBox.

    It should work something like this (untested):

    combo.dropDownFactory = new ClassFactory( CheckBoxList );
    
  18. Dave

    How would I got about handling the individual item clicks? I’d like to call a function and be able to determine which checkbox item was toggled. Whenever I bind a click=”” or change=”” function to the control I get a reference to the entire list instead of the individual items.

  19. Josh Tynjala

    Dave, They’re subclasses of the standard List, so you can use the itemClick event. Also, if you didn’t know about that one, there’s also itemRollOver, itemRollOut, itemDoubleClick, and a couple others that you might like. Check out mx.events.ListEvent.

  20. Albert

    Hi, first of all, congratulations. This was just I was looking for, so thanks.
    Now, I’m trying to use the “advancedlist” component with a custom itemRenderer (just to add an icon by the text), and I’m having problems with disabled items, they appear as normal ones until the mouse pass over them, thats when they get gray background.
    I was expecting the were gray since the beginning, like in your sample.
    I’ve tried both, inline and external itemRenderer.
    It is no so big problem, but I’m wondering if it has a simple solution or I’ve to leave that part.

    Thankyou in advance. Sorry for my English.

  21. Tom

    Some people might be getting disabled list items are showing up as enabled until the cursor rolls over it. (David’s comment). A fix for this is to call the assignment to renderer.enabled before super.drawItem inside the drawItem function override. That way the item will be drawn with settings set by isItemEnabled.

    Replace:

    override protected function drawItem(renderer:IListItemRenderer,
    						selected:Boolean = false,
    						highlighted:Boolean = false,
    						caret:Boolean = false,
    						transition:Boolean = false):void
    {
    	if(renderer) //sometimes renderer is null
    	{
    		super.drawItem(renderer, selected, highlighted && renderer.enabled, caret, transition);
    		renderer.enabled = this.isItemEnabled(renderer.data);
    	}
    }

    With this:

    override protected function drawItem(renderer:IListItemRenderer,
    						selected:Boolean = false,
    						highlighted:Boolean = false,
    						caret:Boolean = false,
    						transition:Boolean = false):void
    {
    	if(renderer) //sometimes renderer is null
    	{
    		renderer.enabled = this.isItemEnabled(renderer.data);
    		super.drawItem(renderer, selected, highlighted && renderer.enabled, caret, transition);
    
    	}
    }
  22. Pingback: Open Source Flex Component: PopUpThumbnail - Josh Talks Flash

  23. Mike N

    Tom, I made your change but it didn’t fix it. Items in the list aren’t redrawn to show their new state (enabled to disabled) until you mouse over them. If useRollover=false, then they are not redrawn by mousing over. Choose one of the list items (my list items are comboBoxes) *then* the list will redraw its correct state (disabled items will be redrawn as disabled, enabled items shown as enabled.)

    Mike – you can set the style of the disabled items using backgroundDisabledColor and disabledColor.

  24. Pingback: Flex 3 ComboBox disabled options

  25. Paul

    Thanks for an awesome tool! I’m using this for an AIR application.

    I’m running into a weird error though. Please let me know if anyone else has come across a similar issue.

    This component is attached on my applications mainwindow. If I maximize this window, for some reason the component’s checkboxes are null, ie, flex throws an exception about a null object reference. However, when I resize, the checkboxes are yet again available.

    Any ideas?

    Thanks!

  26. Josh Tynjala

    Paul, is the null object reference coming from inside one of my list classes, or are you trying to access the list’s internal checkboxes from your own code? If it’s from my code, can you post the stack trace you get when the error is thrown? Thanks!

  27. John

    Josh, I am a complete newb to flex. this is exactly what i was looking for. However can I get a , delimeted list of the values instead of the indices from the checkboxes?

  28. John

    Josh, that returns [object Object] for each item. I have tried selectedItems and selectedItems.toString().

  29. Josh Tynjala

    John, it is a collection of items. You will need to loop over it and grab the properties that you want to see from the items. There is no shortcut here. I’m just telling you where to get the data you need to do it yourself.

  30. Todd

    I want to thank you for all your work building this great component. I have one issue I was hoping you could help on and that is font sizing. I noticed that some of my letters were getting cutoff on the bottom and so I started playing with row height and font size. What I found was that larger fonts (i.e. 15 and above and regardless of the row height) are not displaying fully and appear to be limited to the height of the checkbox control associated with each row.

  31. Josh Tynjala

    Todd, it may be that I’m not measuring the CheckBox height correctly when measuring the renderer, or not setting its dimensions correctly when drawing it. I don’t have time to investigate right now, unfortunately.

  32. Steve

    Really like this component, thanks so much for posting it. I am a newbe and wanted to know if it was even possible to add a number field next to the checkbox item and have the ability to periodically change the number within the field. Just wanted to know if was even possible before I dived into it. Thanks for any feedback you could provide.

  33. Saurav

    Hi Josh,

    Thanks for the tutorial. i tried using the code with flash player 10 flex 3, it shows error when i drag.

    Stack trace:
    Main Thread (Suspended: TypeError: Error #1009: Cannot access a property or method of a null object reference.)
    mx.core::UIComponent/drawFocus
    mx.controls.listClasses::ListBase/showDropFeedback
    mx.controls.listClasses::ListBase/dragEnterHandler
    flash.events::EventDispatcher/dispatchEventFunction [no source]
    flash.events::EventDispatcher/dispatchEvent [no source]
    mx.core::UIComponent/dispatchEvent
    mx.managers.dragClasses::DragProxy/dispatchDragEvent
    mx.managers.dragClasses::DragProxy/mouseMoveHandler

    kindly help.

  34. Josh Tynjala

    Saurav, I’m afraid I haven’t used this code in some time. It’s possible that changes to the framework have caused new bugs. Or, perhaps, it simply never was compatible with the use-case you mention (as used by a PopUpButton). I certainly never tested it in that situation.

  35. Jeroen Beckers

    Great components. I have 1 problem/bug though. I’m using the CheckBoxList and I want all the items to be disabled if the first item is selected. The first item is a ‘use all’ option while the other rows are different sub options.
    []use all
    []book1
    []book2
    []book3

    You get the picture… Now, I set all the enabled properties to false when the first item is selected and I set them to true when it’s unselected. After doing this, the selectedIndices no longer work. If I have 2 items selected and deselect the first, THAT items index is in the selectedIndices while the other (still selected) row isn’t.

    Here’s some code:

    var lst:List = e.currentTarget as List;
    trace(lst.selectedIndices); //this one is correct !!
    
    var dp:ArrayCollection = lst.dataProvider as ArrayCollection;
    if(lst.selectedIndices.length > 0 && lst.selectedIndices[0] == 0)
    {
    	for(var i:int = 1; i< dp.length; i++)
    	{
    		dp.getItemAt(i).canSelect = false;
    	}
    }
    else
    {
    	for(var j:int = 1; j< dp.length; j++)
    	{
    		dp.getItemAt(j).canSelect = true;
    	}
    }
    dp.refresh();
    trace(lst.selectedIndices);//but this one gives the wrong index.

    Has to do with firstSelectionData in the ListBase class, but don't know why …

    Please let me know if you have a solution or if you no longer feel like supporting these components.

    Thanks!

  36. Josh Tynjala

    Jeroen, I don’t really have time to support these components anymore. Best of luck finding the solution. Feel free to post it here if you figure something out.

  37. Felipe

    Hi everyone, i’m new in Flex and i need help urgently!!, how can i check all the checkboxes in the start of the program?… i tried by many days and i got any results. The listbox is fedeed by a httpresponse with the data, and works perfectly, but al the checkboxes are unchecked. PLEASE HELP!!!!! (and sorry the bad english)

  38. Josh Tynjala

    Felipe, try setting the selectedIndices property. Just pass an Array of int values corresponding to each of the items you want selected. For instance, if you want the first three items selected, you’d do this:

    list.selectedIndices = [0, 1, 2];

    If you want all the items selected, then you could use a for loop to go through each item in the data and add its index.

  39. Pingback: consultor java » Selecciones Multiples en Flex VideoTutoriales | Frameworks | Servidores | Aplicaciones Seguras | Performance | Rendimiento | Noticias

  40. Asif Nawaz

    Nice work Josh. Need a help more. What should i change in this code so that “last selected item should remain highlighted” in checkboxList component?

  41. Asif Nawaz

    I used this component in Flex 3 and Flash Builder 4.0, it works fine. But When I used this in Flash Builder 4.5 like
    <toolbox:CheckBoxList id=”checkList” />
    It do not allow to set its id property, rest all other properties can be set. It gives following error.
    1046: Type was not found or was not a compile-time constant: CheckBoxList