Deleting items in a List from an item renderer

It’s easy to delete an item in a spark List from within an item renderer. This is handy if you have a List with a custom renderer that provides a button to delete the item that is associated with that renderer.

You can do this by using the ItemRenderer’s owner property to access the List it is in, drill down to its dataProvider and delete the data item:

<s:ItemRenderer>
    <fx:Script>
        <![CDATA[
                import spark.components.List;
                public function deleteItem():void {
                    var parentList:List = owner as List;
                    // remove the item
                    parentList.dataProvider.removeItemAt(parentList.dataProvider.getItemIndex(data))
                }
            ]]>
        </fx:Script>
        <s:HGroup>
            <s:Label text="{data}" />
            <s:Button id="remove" label="X"  click="deleteItem()"/>
        </s:HGroup>
</s:ItemRenderer>

Another approach is to delete items based on the selectedItem/selectedIndex, but I prefer this method since it allows you to delete items without needing to select them.

Here is an example that uses the deleteItem() method listed above:

View Source

This should work the same way for DataGroup and SkinnableDataContainer as well.

Note: This sample requires Flex SDK 4.0.0.10545 or higher. You can get the latest SDK builds from opensource.adobe.com.

11 thoughts on “Deleting items in a List from an item renderer”

  1. nice, but is it anywhere documented that itemRenderer’s owner is ( and still in later sdk’s ) List control itself?

  2. Here’s a way to do it with a DataGroup, in the same context as the example above:

    public function deleteItem():void {
    DataGroup( this.parent ).dataProvider.removeItemAt( this.itemIndex );
    }

  3. @mzx
    You can use the “is” operator to verify the baseclass:

    if (this.owner is DataGroup) { …

    if (this.owner is List) { …

    Maybe there is an interface for typecasting, or I think in that you can safely typecast the dataprovider like this:

    var dp:IList = Object(this.owner).dataProvider as IList;

  4. This is exactly what I want to accomplish, except that my itemrenderer is not an inline one. How would you access and execute the deleteItem() function if it was not an inline itemrenderer?

  5. @jpeal – I believe the renderer above should work fine whether it is inline or not. This is because the deleteItem() logic is in the renderer itself. If you want to move this logic out of the renderer you might want to use the parentDocument property. Or a more robust approach would be to have the renderer dispatch a custom event on its parent List and then setup a listener for that event.

  6. When deleting items from list, you can run into a very interesting problem which is a side effect of Flex reusing the ItemRenderers. Let’s say you delete an item from the list and add another item with different data, let’s say image. The itemrenderer in a list will have an image from the data that was assigned to it when the list had loaded the first time. To avoid this you can use

    useVirtualLayout=”false”

    which will reload ItemRenderers all the time.

  7. @Martin – It sounds like your item renderer is not optimized for use with virtual layout. This typically happens when your renderer does not reset its state when the data changes (by handling the dataChange event or overriding set data). Also your renderer shouldn’t do anything data specific on creationComplete or related events that only happen when the renderer is first created. I recommend updating your renderer to support this and keep useVirtualLayout true for better performance with larger lists.

    Check out the source of the item renderers in this post for an example of overriding set data: http://flexponential.com/2010/01/10/caching-images-loaded-from-a-spark-item-renderer/

Comments are closed.