actionscript-3apache-flexitemrendererflex-spark

How automatically update itemRenderer state from models flag change


I have an ItemRenderer with a data that has some flags. I need to change the ItemRenderer color depending on these flags. How can I achieve that? This is my IR:

<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
            xmlns:s="library://ns.adobe.com/flex/spark" 
            xmlns:mx="library://ns.adobe.com/flex/mx" 
            autoDrawBackground="false"
            x="{data.x}" y="{data.y}">

<s:states>
    <s:State name="node"/>
    <s:State name="nodeIn"/>
    <s:State name="nodeOut"/>
    <s:State name="nodeTrafficLight"/>
    <s:State name="nodeIntersection"/>
    <s:State name="nodeBlocked"/>
</s:states>

<s:Ellipse width="16" height="16" x="-8" y="-8">
    <s:stroke>
        <s:SolidColorStroke weight="2"
                            color="#FFFF00"
                            color.nodeTrafficLight="#FF00FF"
                            color.nodeIntersection="#FF9900"
                            color.nodeBlocked="#000000"
                            color.nodeIn="#00FF00"
                            color.nodeOut="#FF0000"/>
    </s:stroke>
    <s:fill>
        <s:SolidColor alpha=".5"
                      color="#FFFF00"
                      color.nodeTrafficLight="#FF00FF"
                      color.nodeIntersection="#FF9900"
                      color.nodeBlocked="#000000"
                      color.nodeIn="#00FF00"
                      color.nodeOut="#FF0000"/>
    </s:fill>
</s:Ellipse>

<fx:Script>
    <![CDATA[
        override protected function getCurrentRendererState():String
        {
            if (data.isBlocked)
                return "nodeBlocked";

            if (data.isIn)
                return "nodeIn";

            if (data.isOut)
                return "nodeOut";

            if (data.isIntersection)
                return "nodeIntersection";

            return "node";
        }
    ]]>
</fx:Script>
</s:ItemRenderer>

But I don't get these states updated when some of these flags (eg. data.isIn) change. My model has [Bindable] tag.


Solution

  • First off; I don't think the x and y values have an affect inside a renderer. The list class will handle the positioning of the renderer.

    That said, you're renderer does not respond to the dataChange event; so the renderer will not update itself when the data changes. Add a dataChange event handler:

    <s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
                xmlns:s="library://ns.adobe.com/flex/spark" 
                xmlns:mx="library://ns.adobe.com/flex/mx" 
                autoDrawBackground="false"
                dataChange="onDataChange(event)">
    
    
    <fx:Script>
        <![CDATA[
          protected function onDataChange(event:Event):void{
              invalidateRendererState();
          }
        ]]>
    </fx:Script>
    

    The invalidateRendererState() method should force commitProperties() to re-run; which will in turn force getCurrentRendererState() to execute.

    If for some reason the onDataChange() event is not firing when you change the data in your dataProvider; you'll have to use the itemUpdated() or refresh() function on your dataProvider to 'announce' that you changed data.