10 Replies Latest reply on Aug 17, 2007 2:46 PM by Josh Johnson

    Creating a common itemRenderer different data properties

    Josh Johnson Level 1
      Ok, first let me set the context. I creating a dashboard-like table where each row represents an object, and the first column of the table shows the name of the object and subsequent columns are various dashboard compliance items.

      [Name] [Prop A] [Prop B] [Prop C] [Prop D]
      Item 1 {graphic) {graphic) {graphic) {graphic)
      Item 2 {graphic) {graphic) {graphic) {graphic)
      Item 3 {graphic) {graphic) {graphic) {graphic)

      Each dashboard cell displays a different graphic based on that property. There are 6 graphics, so the itemRenderer looks at the data for that given property, and then translates the #0-#5 into a class reference for 1 of those 6 graphics using the Switch method.

      override public function set data(value:Object):void {
      super.data = value;
      switch(value.type) {
      case 0:
      img.source = scanFailed8;
      break;
      case 1:
      img.source = needsScan8;
      break;
      etc...

      So since the calculation is the same for all of these properties, what I want to do is create a generic itemRenderer where I can pass in the property name and then use that reference in the Switch method. My problem is that the Switch method works fine if it's:

      switch(value.PropA)

      But in need to set a public variable that can get passed in to replace that value. I tried this as a string, and that clearly failed. Can someone help me get through this issue? I really don't want to have to maintain a separate item renderer for each property. :)

      Thanks.
        • 1. Re: Creating a common itemRenderer different data properties
          ntsiii Level 3
          Your itemRenderer needs to implement IDropInListItemRenderer. This interface gives you access to the listData object, which has stuff like column Index, dataField, and other info about the whole list.

          There is an example in the docs here:
          http://livedocs.adobe.com/flex/2/docs/00000834.html
          and in the comments, there is another link to an example.

          This is not difficult.

          Tracy
          • 2. Re: Creating a common itemRenderer different data properties
            Josh Johnson Level 1
            Thanks Tracy, I'll check it out. I'm still comfortable in the world of writing mxml and ActionScript for functionality like I would've written JavaScript for an HTML app. I haven't quite made the leap into the class hierarchy and the down-and-dirty Flash stuff. Guess there's no time like the present though. :)
            • 3. Re: Creating a common itemRenderer different data properties
              ntsiii Level 3
              It is easier than it sounds. Just start with a simple example.
              Tracy
              • 4. Re: Creating a common itemRenderer different data properties
                Josh Johnson Level 1
                So I'm getting a little stuck here. In the examples, the item renderer is based on a component like a textArea that has a listData attribute, so casting listData to a variable is very easy. But in my case, I need the renderer to contain both an image and a text label, so the base component is an HBox which doesn't have the listData property. It seems wrong that I should have to cast listData twice (once for image and again for label) since all I'm really trying to pull is the dataField information from the ItemRenderer. Any thoughts? Have I gone way off track here?
                • 5. Re: Creating a common itemRenderer different data properties
                  jmryan
                  How about using the DataGrid instead of Grid or List containers? If so, the listData property will actually be a DataGridListData (I think, or similar) which has more pertinent information for what you're trying to accomplish.
                  • 6. Re: Creating a common itemRenderer different data properties
                    Josh Johnson Level 1
                    Not sure I'm understanding you jmryan. I am using a DataGrid, and then I'm crafting a custom item renderer for cells in that DataGrid. If my custom renderer was based on a component that already implements listData (i.e. Image) then it worked fine, but I wanted to base the renderer on a container (HBox) that doesn't implement listData.

                    After a little digging, I think I've got it close to working with the following code:

                    <?xml version="1.0" encoding="utf-8"?>
                    <mx:HBox
                    xmlns:mx=" http://www.adobe.com/2006/mxml"
                    implements="mx.controls.listClasses.IDropInListItemRenderer"
                    horizontalAlign="center" verticalAlign="middle">

                    <mx:Script>
                    <![CDATA[
                    import mx.controls.listClasses.BaseListData;
                    import mx.controls.dataGridClasses.DataGridListData;
                    import flash.events.Event;

                    //private var _listData:DataGridListData;
                    private var _listData:BaseListData;
                    // Make the listData property bindable.
                    [Bindable("dataChange")]
                    // Define the getter method.
                    public function get listData():BaseListData {
                    return _listData;
                    }
                    // Define the setter method,
                    public function set listData(value:BaseListData):void {
                    _listData = value;
                    }

                    public function init():void {
                    // When data changes the handleDataChanged function is called
                    addEventListener("dataChange", handleDataChanged);
                    }

                    public function handleDataChanged(event:Event):void {
                    // Cast listData to DataGridListData object.
                    var theListData:DataGridListData = DataGridListData(listData);
                    // Access information about the data passed to the item renderer.
                    theText.text = theListData.dataField + " = " + theListData.label;
                    }

                    ]]>
                    </mx:Script>
                    <mx:Label id="theText" />

                    </mx:HBox>

                    Now I just have to put back my Switch function and have it fill in an Image.source along with the Label.text.
                    • 7. Re: Creating a common itemRenderer different data properties
                      Josh Johnson Level 1
                      Doh, I just noticed I left the 'preinitialize="init()"' out of the HBox. Should've been:

                      <mx:HBox
                      xmlns:mx=" http://www.adobe.com/2006/mxml"
                      implements="mx.controls.listClasses.IDropInListItemRenderer"
                      horizontalAlign="center" verticalAlign="middle"
                      preinitialize="init()">
                      • 8. Re: Creating a common itemRenderer different data properties
                        ntsiii Level 3
                        Ah, that looks pretty good. Let us know when you get it working all the way, i may use it to build an example itemRenderer that uses list data in mxml.

                        Tracy
                        • 9. Re: Creating a common itemRenderer different data properties
                          Josh Johnson Level 1
                          Finally got it. The last thing I was missing was changing the Switch statement cases to check for the numbers as strings. Once I quoted them, it all fell into place. Once I get back to my other computer (with the code on it) I'll post for mass consumption. Thanks Tracy!!!
                          • 10. Re: Creating a common itemRenderer different data properties
                            Josh Johnson Level 1
                            OK, here it is in all it's infamy....

                            <?xml version="1.0" encoding="utf-8"?>
                            <mx:HBox
                            xmlns:mx=" http://www.adobe.com/2006/mxml"
                            implements="mx.controls.listClasses.IDropInListItemRenderer"
                            horizontalAlign="center" verticalAlign="middle"
                            horizontalScrollPolicy="off" verticalScrollPolicy="off"
                            preinitialize="preinit()" creationComplete="init()">

                            <mx:states>
                            <mx:State name="long">
                            <mx:SetStyle name="horizontalAlign" value="left"/>
                            <mx:SetStyle name="paddingLeft" value="10"/>
                            </mx:State>
                            <mx:State name="short">
                            <mx:RemoveChild target="{theLabel}"/>
                            </mx:State>
                            </mx:states>

                            <!--Load classes for image sources -->
                            <mx:Script source="../Scripts/LoadIcons.as" />
                            <mx:Script>
                            <![CDATA[
                            import mx.controls.listClasses.BaseListData;
                            import mx.controls.dataGridClasses.DataGridListData;
                            import flash.events.Event;

                            [Bindable]
                            public var showLongFormat:Boolean;

                            //private var _listData:DataGridListData;
                            private var _listData:BaseListData;
                            // Make the listData property bindable.
                            [Bindable("dataChange")]

                            // Define the getter method for listData.
                            public function get listData():BaseListData {
                            return _listData;
                            }
                            // Define the setter method for listData
                            public function set listData(value:BaseListData):void {
                            _listData = value;
                            }
                            public function preinit():void {
                            // When data changes the handleDataChanged function is called
                            addEventListener("dataChange", handleDataChanged);
                            }
                            public function handleDataChanged(event:Event):void {
                            // Cast listData to DataGridListData object.
                            var theListData:DataGridListData = DataGridListData(listData);
                            // Access information about the data passed to the item renderer
                            // and spit out the right image and text.
                            switch(theListData.label) {
                            case '0':
                            theIcon.source = scanFailed8;
                            theIcon.toolTip = theListData.dataField + ': Scan Failed';
                            theLabel.text = 'Scan Failed';
                            break;
                            case '1':
                            theIcon.source = needsScan8;
                            theIcon.toolTip = theListData.dataField + ': Needs Scanning';
                            theLabel.text = 'Needs Scanning';
                            break;
                            case '2':
                            theIcon.source = scanning8;
                            theIcon.toolTip = theListData.dataField + ': Scanning';
                            theLabel.text = 'Scanning';
                            break;
                            case '3':
                            theIcon.source = noncompliant8;
                            theIcon.toolTip = theListData.dataField + ': Non-Compliant';
                            theLabel.text = 'Non-Compliant';
                            break;
                            case '4':
                            theIcon.source = partial8;
                            theIcon.toolTip = theListData.dataField + ': Partial Compliance';
                            theLabel.text = 'Partial Compliance';
                            break;
                            case '5':
                            theIcon.source = compliant8;
                            theIcon.toolTip = theListData.dataField + ': Compliant';
                            theLabel.text = 'Compliant';
                            break;
                            default:
                            theIcon.source = notApplicable8;
                            theIcon.toolTip = 'Not Applicable';
                            break;
                            }
                            }

                            // Check to see if form is 'long' or 'short'
                            public function init():void {
                            if (showLongFormat == true) {
                            currentState='long';
                            }else{
                            currentState='short';
                            }
                            }
                            ]]>
                            </mx:Script>
                            <mx:Image id="theIcon" />
                            <mx:Label id="theLabel" />
                            </mx:HBox>

                            That's a lot of code to just stick an image in a cell. Ok, I guess it does a little more than that. ;-)