0

have an advanced datagrid with a simple custom mxadvanceddatagriditemrenderer. I want the renderer to only display an image when the row is hovered or selected. Right now I am doing that by using the excludeFrom="normal" tag on my image.

It works fine (minus the selected state, it disappears when selected) when I have the states hovered and normal defined. When I try to define a selected state, upon row click I get the following error:

RangeError: Index 0 is out of range.
    at spark.components::Group/checkForRangeError()[E:\dev\4.x\frameworks\projects\spark\src\spark\components\Group.as:1106]
    at spark.components::Group/setElementIndex()[E:\dev\4.x\frameworks\projects\spark\src\spark\components\Group.as:1265]
    at spark.components::Group/addElementAt()[E:\dev\4.x\frameworks\projects\spark\src\spark\components\Group.as:1167]
    at mx.states::AddItems/addItemsToContentHolder()[E:\dev\4.x\frameworks\projects\framework\src\mx\states\AddItems.as:737]
    at mx.states::AddItems/apply()[E:\dev\4.x\frameworks\projects\framework\src\mx\states\AddItems.as:545]
[E:\dev\4.x\frameworks\projects\framework\src\mx\core\UIComponent.as:9961] ... etc

Has anyone experienced this before or know a solution?

Thanks

EDIT: the code involved is very simple:

<s:MXAdvancedDataGridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" focusEnabled="false">
<fx:Script>
<![CDATA[
import mx.collections.IList;
protected function removeRow(event:MouseEvent):void
{
var ind :int = IList(parentDocument.dataGrid.dataProvider).getItemIndex(data);
IList(parentDocument.dataGrid.dataProvider).removeItemAt(ind);
}   
]]>
</fx:Script>
<s:states>
<s:State name="normal" />
<s:State name="hovered"/>
<s:State name="selected"/>
</s:states>
<mx:Image id="removeButton" excludeFrom="normal" source="@Embed(source='../assets/icons/close_icon.gif')" click="removeRow(event)" width="10" height="10" alpha=".5" toolTip="{resourceManager.getString('localization', 'REMOVE')}"/>
</s:MXAdvancedDataGridItemRenderer>
CodeMonkey
  • 174
  • 10

1 Answers1

1

It would seem - though admiddetly it's a bit of a guess - that you're trying to remove the itemrenderer while changing its state (to 'selected' by clicking on it) at the same time.

Here's my solution for the kind of situation where you want to remove an itemrenderer by clicking on it: just make it dispatch a bubbling "remove" event and let some kind of controller handle the removal.

So your itemrender might look like this:

<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
                xmlns:s="library://ns.adobe.com/flex/spark">

    <fx:Script>
        <![CDATA[
            import mx.events.FlexEvent;
        ]]>
    </fx:Script>

    <s:states>
        <s:State name="normal" />
        <s:State name="hovered" />
        <s:State name="selected" />
    </s:states>

    <!-- some other stuff -->

    <s:Button label="remove me" excludeFrom="normal"
              click="dispatchEvent(new FlexEvent(FlexEvent.REMOVE, true))" />

</s:ItemRenderer>

The 'true' value there is important to make the event bubble all the way down to the List component.

Then in a controller that has a reference to the List (or DataGrid) or perhaps in a subclass of List (or DataGrid), you trap that event and remove the item.

theList.addEventListener(FlexEvent.REMOVE, handleRemoveRequest);

private function handleRemoveRequest(event:FlexEvent):void {
    var itemRender:IItemRenderer = event.target as IITemrenderer;
    var item:SomeClass = itemRender.data;
    var index:int = theDataProvider.getItemIndex(item);
    theDataProvider.removeItemAt(index);
}

Here it's important that you use target instead of currentTarget because the former will be the ItemRenderer and the latter will be the List itself.

RIAstar
  • 11,912
  • 20
  • 37
  • Thanks for the answer attempt, but my problem does not lie there. I had no problem removing the row before introducing states into the mix. My problem is when I click the row, the existance of a selected state somehow crashes deep within the flex code. The image never has a chance to show or be clicked. I am thinking this is a bug with adobe. – CodeMonkey May 31 '11 at 16:27
  • Well, you could always just hide the image in the 'normal' state instead of completely removing it (alpha="0" or visible="false"). Doesn't feel like good practice though: having an item remove itself from its collection. Have you tried my approach and seen if there was any difference? I have done this many times without any issues. – RIAstar May 31 '11 at 22:41
  • The alpha suggestion worked. I set alpha.normal to 0 and its general alpha and it works in all states. I tested visible in the same way and it worked as well. I wonder why it explodes when I try includeIn or ExcludeFrom? I admit I didn't try your code but also I'm not sure what the difference is between an mxadvanceddatagridrenderer and the spark itemrenderer – CodeMonkey May 31 '11 at 23:29
  • You can use them in the same way, since they both implement IItemRenderer. So in my example you can substitute for just like that. Sorry I didn't point that out. – RIAstar Jun 01 '11 at 10:15
  • I ended up taking your suggestion that an item shouldn't remove itself from the datagrid – CodeMonkey Jun 27 '11 at 22:39