13 Replies Latest reply on Sep 14, 2008 8:19 PM by denisputnam

    How do I get access to an AdvancedDataGridRendererProvider?

    denisputnam
      In the snippet of the following code:

      <mx:rendererProviders>
      <mx:AdvancedDataGridRendererProvider depth="2" column="{protocolID}" columnSpan="1" renderer="ProtocolComboBox"/>
      </mx:rendererProviders>

      Can someone tell me how to get access to the ProtocolComboBox renderer? I can't find an example anywhere.

        • 1. Re: How do I get access to an AdvancedDataGridRendererProvider?
          Level 7

          "denisputnam" <webforumsuser@macromedia.com> wrote in message
          news:ga5nua$pkr$1@forums.macromedia.com...
          > In the snippet of the following code:
          >
          > <mx:rendererProviders>
          > <mx:AdvancedDataGridRendererProvider depth="2" column="{protocolID}"
          > columnSpan="1" renderer="ProtocolComboBox"/>
          > </mx:rendererProviders>
          >
          > Can someone tell me how to get access to the ProtocolComboBox renderer? I
          > can't find an example anywhere.

          What are you trying to do?


          • 2. Re: How do I get access to an AdvancedDataGridRendererProvider?
            denisputnam Level 1
            Hello Amy,

            Thank you for responding.

            I have set up an AdvancedDataGrid using a GroupCollection that has a source of an ArrayCollection that is populated by an HTTP service. I have set up a custom component that extends a ComboBox called ProtocolComboBox. The combo box has two entries, "sftp" and "ftp". What I want to do is to set the current selection in the combo box to reflect what was read previously from the HTTP service. To do this, I need to get reference to the ProtocolComboBox that was rendered in the AdvancedDataGrid so that I can call methods in it to set the selection to correct value based on what on what was previously read. Right now I have tried the following:

            var myR:Array = this.rendererProviders;
            var myCf:ClassFactory = myR[0].renderer;
            var myCb:Object = myCf.generator;
            var myComboBox:ProtocolComboBox = myCb as ProtocolComboBox;
            myComboBox.init( myCursor.current.protocol );

            However the myCombox object is null. Can you tell me how to do this?

            • 3. Re: How do I get access to an AdvancedDataGridRendererProvider?
              Level 7

              "denisputnam" <webforumsuser@macromedia.com> wrote in message
              news:ga6dls$m2l$1@forums.macromedia.com...
              > Hello Amy,
              >
              > Thank you for responding.
              >
              > I have set up an AdvancedDataGrid using a GroupCollection that has a
              > source of
              > an ArrayCollection that is populated by an HTTP service. I have set up a
              > custom component that extends a ComboBox called ProtocolComboBox. The
              > combo
              > box has two entries, "sftp" and "ftp". What I want to do is to set the
              > current
              > selection in the combo box to reflect what was read previously from the
              > HTTP
              > service. To do this, I need to get reference to the ProtocolComboBox that
              > was
              > rendered in the AdvancedDataGrid so that I can call methods in it to set
              > the
              > selection to correct value based on what on what was previously read.
              > Right
              > now I have tried the following:
              >
              > var myR:Array = this.rendererProviders;
              > var myCf:ClassFactory = myR[0].renderer;
              > var myCb:Object = myCf.generator;
              > var myComboBox:ProtocolComboBox = myCb as ProtocolComboBox;
              > myComboBox.init( myCursor.current.protocol );
              >
              > However the myCombox object is null. Can you tell me how to do this?

              You need to override the set data method in your component and set the value
              there
              http://www.adobe.com/devnet/flex/articles/itemrenderers_pt1.html


              • 4. Re: How do I get access to an AdvancedDataGridRendererProvider?
                denisputnam Level 1
                Hi Amy,

                I think this is going to get me somewhere. Can you send me the link to the part 2 for the external renderer's? I get
                Access denied
                We're sorry, you are not allowed access to the service you requested.

                If you feel you should have access, please contact the appropriate authorities and give them your IP address: 71.126.131.4

                Thank you for your patience.

                When I try access the link.
                • 5. Re: How do I get access to an AdvancedDataGridRendererProvider?
                  denisputnam Level 1
                  Hi Amy,

                  Never mind, I found another route to it.
                  • 6. Re: How do I get access to an AdvancedDataGridRendererProvider?
                    denisputnam Level 1
                    Hi Amy,

                    I looked at the url's that you gave me, but I still can't quite grasp it. Given something like:

                    <mx:AdvancedDataGrid xmlns:mx=" http://www.adobe.com/2006/mxml" selectionMode="multipleCells" enabled="true" dataProvider="{myTransferInfoGroupColl}">
                    <mx:columns>
                    <mx:AdvancedDataGridColumn headerText="ClientName" width="110" editable="false" dataField="name"/>
                    <mx:AdvancedDataGridColumn headerText="Client ID" editable="false" dataField="client_id"/>
                    <mx:AdvancedDataGridColumn headerText="Transfer ID" width="110" editable="false" dataField="transfer_id"/>
                    <mx:AdvancedDataGridColumn headerText="Transfer Name" width="120" editable="false" dataField="transfer_name"/>
                    <mx:AdvancedDataGridColumn headerText="Endpoint" dataField="endpoint"/>
                    <mx:AdvancedDataGridColumn headerText="Host" dataField="host" />
                    <mx:AdvancedDataGridColumn headerText="User" dataField="user" />
                    <mx:AdvancedDataGridColumn headerText="Login Pwd" dataField="login_pwd"/>
                    <mx:AdvancedDataGridColumn headerText="Protocol" dataField="protocol" id="protocolID">
                    </mx:AdvancedDataGridColumn>
                    <mx:AdvancedDataGridColumn headerText="Platform" dataField="platform"/>
                    </mx:columns>
                    <mx:rendererProviders>
                    <mx:AdvancedDataGridRendererProvider depth="2" column="{protocolID}" columnSpan="1" renderer="{ProtocolComboBox}"/>
                    </mx:rendererProviders>
                    </mx:AdvancedDataGrid>

                    I still can't see how to get the dataProvider down to the renderer="{ProtocolComboBox}".

                    when I do the
                    override public function set data( value:Object ): void
                    {
                    super.data = value; // How do I get the list of values into this point in the code?
                    }

                    The DataGrid examples that you showed me allow you to use dataProvider="{protocolArray}" that will cause the set data() function to be invoked. How do I accomplish this with the mx:AdvancedDataGridRendererProvider? If I could something like renderer={ProtocolComboBox( myArray )}, then I think it would work, but this causes a syntax error.
                    • 7. Re: How do I get access to an AdvancedDataGridRendererProvider?
                      Level 7

                      "denisputnam" <webforumsuser@macromedia.com> wrote in message
                      news:ga6sko$9om$1@forums.macromedia.com...
                      > Hi Amy,
                      >
                      > I think this is going to get me somewhere. Can you send me the link to
                      > the
                      > part 2 for the external renderer's? I get

                      http://www.adobe.com/devnet/flex/articles/itemrenderers_pt2.html


                      • 8. Re: How do I get access to an AdvancedDataGridRendererProvider?
                        denisputnam Level 1
                        Hi Amy,

                        This was helpful, but I still can't figure out how to get the combo box to render the data from the parent. I can get the combo box to render an internal array, but I want the parent to be able to pass the array to the combo box and then set the selectedItem. Given the following code, can you tell me how to do this? I have tried using the dataField property, but that caused the combo box to not render. With DataGrid's this is fairly straight forward, but it is not with the AdvancedDataGrid. What am I missing?

                        <mx:AdvancedDataGridColumn headerText="Protocol" id="protocolID" resizable="true" itemEditor="ProtocolComboBox" visible="true" rendererIsEditor="true"/>
                        </mx:columns>
                        <mx:rendererProviders>
                        <mx:AdvancedDataGridRendererProvider depth="2" column="{protocolID}" columnSpan="1" renderer="ProtocolComboBox" id="r1"/>
                        </mx:rendererProviders>

                        <?xml version="1.0" encoding="utf-8"?>
                        <mx:ComboBox xmlns:mx=" http://www.adobe.com/2006/mxml" selectedIndex="0" editable="false" enabled="true" dataProvider="{myARR}" visible="false">
                        <mx:Script>
                        <![CDATA[
                        [Bindable]
                        public var myARR:Array = [ "sftp", "ftp" ];
                        override public function set data(value:Object):void
                        {
                        super.data = value;
                        }
                        ]]>
                        </mx:Script>
                        </mx:ComboBox>
                        • 9. Re: How do I get access to an AdvancedDataGridRendererProvider?
                          Level 7

                          "denisputnam" <webforumsuser@macromedia.com> wrote in message
                          news:ga8m3s$fjd$1@forums.macromedia.com...
                          > Hi Amy,
                          >
                          > This was helpful, but I still can't figure out how to get the combo box to
                          > render the data from the parent. I can get the combo box to render an
                          > internal
                          > array, but I want the parent to be able to pass the array to the combo box
                          > and
                          > then set the selectedItem. Given the following code, can you tell me how
                          > to do
                          > this? I have tried using the dataField property, but that caused the
                          > combo box
                          > to not render. With DataGrid's this is fairly straight forward, but it is
                          > not
                          > with the AdvancedDataGrid. What am I missing?
                          >
                          > <mx:AdvancedDataGridColumn headerText="Protocol" id="protocolID"
                          > resizable="true" itemEditor="ProtocolComboBox" visible="true"
                          > rendererIsEditor="true"/>
                          > </mx:columns>
                          > <mx:rendererProviders>
                          > <mx:AdvancedDataGridRendererProvider depth="2" column="{protocolID}"
                          > columnSpan="1" renderer="ProtocolComboBox" id="r1"/>
                          > </mx:rendererProviders>
                          >
                          > <?xml version="1.0" encoding="utf-8"?>
                          > <mx:ComboBox xmlns:mx=" http://www.adobe.com/2006/mxml" selectedIndex="0"
                          > editable="false" enabled="true" dataProvider="{myARR}" visible="false">
                          > <mx:Script>
                          > <![CDATA[
                          > [Bindable]
                          > public var myARR:Array = [ "sftp", "ftp" ];
                          > override public function set data(value:Object):void
                          > {
                          > super.data = value;
                          > }
                          > ]]>
                          > </mx:Script>
                          > </mx:ComboBox>

                          Arrays aren't bindable. You should be seeing a warning at the line
                          dataProvider="{myARR}". So that's why I'm changing your myArr value to an
                          ArrayCollection. Try something like:

                          http://www.cflex.net/showfiledetails.cfm?ChannelID=1&Object=File&objectID=767


                          • 10. Re: How do I get access to an AdvancedDataGridRendererProvider?
                            ntsiii Level 3
                            Let me take a minute to explain why this is so complicated.

                            First, with ComboBox, you cannot set the selected item like you might expect. ComboBox.selectedItem is writable, but you must assign it a reference to an actual item in its dataProvider for that to work. You can't do that if you are getting a value from a data service call. So to set the selectedItem, you must loop ove the dataProvider items, and compare the appropriate property value to the value you are trying to match. When a match is found, you use the loop index to set the selectedIndex.

                            So to even start to put a ComboBox in an itemrenderer, you must first extend ComboBox to do this loop and match. The "ComboBoxSelectedValue.mxml" component in that example does this. Further complicating this is that to be generally useful, you must be able to define the field in the CBX items that contains the data you want to match.

                            Your case, with a simple, static dataProvider for the combo box. will let you simplify that extended ComboBox a lot.

                            Second, interactive itemRenderers are complicated in themselves. They are re-used, for example when you scroll, so all state that depends on the row-level data must be set in the set data() override. Actually in commitProperties or updateDisplayList, but you wil see that in the example.

                            That example provides for having a different dataProvider for each row. You do not need that so focus on the static dataProvider example.

                            Kinda complicated, but it has to be to be flexible.

                            Tracy
                            • 11. Re: How do I get access to an AdvancedDataGridRendererProvider?
                              denisputnam Level 1
                              Hello,

                              Thank you for responding to my query. The piece of information that I was missing was the fact that the values of the AdvancedDataGrid are passed to the renderer via the "data" property. After I realized this things got a whole lot easier. So what I did was to write a custom control which extends the ComboBox. I also wrote a custom event that has a forth argument that contains the value of the item the user selected in the ComboBox. My custom ComboBox then dispatches this event to the parent which I set up with a listener for the custom event.

                              The code looks something like:

                              public function myHandler( evt:ProtocolComboBoxEvent ):void
                              {
                              var mySelection:String = evt.selection;
                              var i:int = this.selectedIndex;
                              trace( "MasterTransferGrid.myHandler(): " + mySelection );
                              }
                              This allows me to get the user selection from the event and get the selected row in the AdvancedDataGrid.

                              I also had issues because the AdvancedDataGrid was renderering both text value and the ComboBox in the same cell. To overcome this, I had to set some attributes in the constructor do the following:

                              public function ProtocolComboBoxRenderer()
                              {
                              super();
                              super.visible = false;
                              super.enabled = true;
                              super.editable= false;
                              super.dataProvider = myAC;
                              super.selectedIndex = 0;
                              this.addEventListener(DropdownEvent.CLOSE, closeHandler);
                              }

                              And in the AdvancedDataGrid I had to do:

                              <mx:AdvancedDataGridColumn headerText="Protocol" id="protocolID" resizable="false" itemEditor="ProtocolComboBox" visible="true" rendererIsEditor="true"/>

                              So I had to set visible and rendererIsEditor to true in the column description and in the constructor I had to set visible and editable to false, otherwise the item renderer and the item editor both render into the cell at the same time. This produced weird behavior.

                              The complicated part of this whole thing is trying to figure out the "handshake" between the AdvancedDataGrid and its renderers. So basically it comes down to the following:

                              1. The AdvancedDataGrid's data is passed to the renderer via the "data" property which the renderer can see.
                              2. The renderer then communicates what the user does via a dispatched event that the parent must listen for.
                              3. Set the attributes for the AdvancedDataColumn for visible and itemIsEditor to true.
                              4. Set the attributes for the extended ComboBox for visible and editable to false.

                              Once you figure this out, it is fairly simple. Unfortunately, the books that I have purchased to learn FLEX do not show simple examples of this. They show how to set up the renderers, but they don't show you how to pass information back and forth.

                              Have I misunderstood all of this? Am I doing it in a less-than-efficient way?

                              Thank you so much for your assistance.
                              • 12. Re: How do I get access to an AdvancedDataGridRendererProvider?
                                denisputnam Level 1
                                Well I was wrong about the setting the attributes. Now I am getting bleed over from the events. Clicking on a ComboBox on one column causes the others to update to the original values. Ugh!
                                • 13. Re: How do I get access to an AdvancedDataGridRendererProvider?
                                  denisputnam Level 1
                                  Okay I think I got this. Part of the solution came from here:

                                  http://www.cflex.net/showfiledetails.cfm?ChannelID=1&Object=File&objectID=767

                                  Here is the code for the renderer:

                                  package com.moveit
                                  {
                                  import flash.events.*;

                                  import mx.controls.ComboBox;
                                  import mx.events.*;

                                  public class PlatformComboBoxRenderer extends ComboBox
                                  {
                                  import mx.collections.ArrayCollection;
                                  import mx.controls.advancedDataGridClasses.AdvancedDataGridListData;

                                  private var _oItem:String;

                                  private var myARR:Array = [ "linux", "solaris", "aix" ];
                                  private var myAC:ArrayCollection = new ArrayCollection( myARR );

                                  public function PlatformComboBoxRenderer()
                                  {
                                  super();
                                  this.visible = false;
                                  this.enabled = true;
                                  this.editable= false;
                                  this.dataProvider = myAC;
                                  this.selectedIndex = 0;
                                  this.addEventListener(ListEvent.CHANGE, onChangeCBOSelection );
                                  }

                                  public function onChangeCBOSelection( oEvent:Event ):void
                                  {
                                  _oItem = oEvent.target.selectedItem;
                                  this.dispatchEvent( new PlatformComboBoxEvent( PlatformComboBoxEvent.PLATFORM_COMPLETE, true, false, this.selectedItem.toString() ) );

                                  }
                                  override public function set data(value:Object):void
                                  {
                                  if( value != null )
                                  {
                                  super.data = value;
                                  _oItem = value.platform;
                                  invalidateProperties();
                                  }
                                  }
                                  override protected function commitProperties():void
                                  {
                                  super.commitProperties();
                                  if( _oItem )
                                  {
                                  setSelectedValue();
                                  }
                                  }
                                  private function setSelectedValue():void
                                  {
                                  this.selectedItem = _oItem;
                                  }
                                  }

                                  <mx:AdvancedDataGrid xmlns:mx=" http://www.adobe.com/2006/mxml" selectionMode="multipleRows" enabled="true" dataProvider="{myTransferInfoGroupColl}">
                                  <mx:columns>
                                  <mx:AdvancedDataGridColumn headerText="ClientName" width="110" editable="false" dataField="name"/>
                                  <mx:AdvancedDataGridColumn headerText="Client ID" editable="false" dataField="client_id"/>
                                  <mx:AdvancedDataGridColumn headerText="Transfer ID" width="110" editable="false" dataField="transfer_id"/>
                                  <mx:AdvancedDataGridColumn headerText="Transfer Name" width="120" editable="false" dataField="transfer_name"/>
                                  <mx:AdvancedDataGridColumn headerText="Endpoint" dataField="endpoint"/>
                                  <mx:AdvancedDataGridColumn headerText="Host" dataField="host" />
                                  <mx:AdvancedDataGridColumn headerText="User" dataField="user" />
                                  <mx:AdvancedDataGridColumn headerText="Login Pwd" dataField="login_pwd"/>
                                  <mx:AdvancedDataGridColumn headerText="Platform" id="platformID" itemEditor="com.moveit.PlatformComboBoxRenderer" visible="true" editable="false" rendererIsEditor="false"/>
                                  <mx:AdvancedDataGridColumn headerText="Protocol" id="protocolID" itemEditor="com.moveit.ProtocolComboBoxRenderer" visible="true" editable="false" rendererIsEditor="false"/>
                                  </mx:columns>
                                  <mx:rendererProviders>
                                  <mx:AdvancedDataGridRendererProvider depth="2" column="{platformID}" columnSpan="1" renderer="com.moveit.PlatformComboBoxRenderer"/>
                                  <mx:AdvancedDataGridRendererProvider depth="2" column="{protocolID}" columnSpan="1" renderer="com.moveit.ProtocolComboBoxRenderer"/>
                                  </mx:rendererProviders>

                                  public function init():void
                                  {
                                  myTransferInfoHttp = new HTTPService();

                                  // Insert your domain name
                                  myTransferInfoHttp.url = " http://freedom.dynalias.org/cgi-bin/SourceBasicTransferInfoDataGrid.cgi";

                                  CursorManager.setBusyCursor();

                                  myTransferInfoHttp.send();
                                  myTransferInfoHttp.addEventListener(ResultEvent.RESULT, resultTransferInfoHttpHandler);
                                  myTransferInfoHttp.addEventListener(FaultEvent.FAULT, faultTransferInfoHttpHandler);
                                  this.addEventListener( ProtocolComboBoxEvent.PROTOCOL_COMPLETE, this.protocolComboBoxHandler );
                                  this.addEventListener( PlatformComboBoxEvent.PLATFORM_COMPLETE, this.platformComboBoxHandler );

                                  }

                                  public function platformComboBoxHandler( evt:PlatformComboBoxEvent ):void
                                  {
                                  var mySelection:String = evt.selection;
                                  var i:int = this.selectedIndex;
                                  var myIndex:int = this.selectedIndex - 1;
                                  trace( "MasterTransferGrid.platformComboBoxHandler(): " + mySelection );
                                  var record:Array = this.masterGridAC.getItemAt( myIndex ) as Array;
                                  record["platform"] = evt.selection; //myCursor.current.platform;
                                  }

                                  It is important to set the renderer and the visible attributes as:

                                  itemEditor="com.moveit.PlatformComboBoxRenderer" visible="true"

                                  and in the constructor:

                                  this.visible = false;
                                  this.enabled = true;
                                  this.editable= false;

                                  It seems to be important to store the values within the renderer rather than relying on the super class values. Adding the onChange handler and then invalidating the properties and then committing them again on the override of the commitProperties().