11 Replies Latest reply on Feb 26, 2009 2:46 PM by Newsgroup_User

    Setting component properties in itemRenderer

    ac361 Level 1
      Hi. I've created a custom itemRenderer for a DataGrid that has a TextInput and a Button. When the user clicks the button, the Application needs to present a Browse window and display the file the user chose in the TextInput of the itemRenderer. I've created a custom event that bubbles to the Application level; is it good programming practice to pass references to the controls in the itemRenderer via the event? If not, can you suggest a better way? Thank you.
        • 1. Re: Setting component properties in itemRenderer
          Level 7

          "curious_Lee" <webforumsuser@macromedia.com> wrote in message
          news:go6dfc$gnd$1@forums.macromedia.com...
          > Hi. I've created a custom itemRenderer for a DataGrid that has a TextInput
          > and
          > a Button. When the user clicks the button, the Application needs to
          > present a
          > Browse window and display the file the user chose in the TextInput of the
          > itemRenderer. I've created a custom event that bubbles to the Application
          > level; is it good programming practice to pass references to the controls
          > in
          > the itemRenderer via the event? If not, can you suggest a better way?
          > Thank you.

          The event will already have a reference to your renderer.


          • 2. Re: Setting component properties in itemRenderer
            JeffryHouser Level 4
            Amy,
            He said it was a custom event; unless he put it there it would not have reference to the itemRenderer.

            curious_Lee,

            Adding a reference to the itemRenderer is perfectly fine and is used all the time in the Flex Framework.

            However, based on your description I wonder if it would be better to put the browse code within the itemRenderer as opposed to the main application. It's hard to say based on the little I know about your app.
            • 3. Re: Setting component properties in itemRenderer
              ac361 Level 1
              Thank you for the information. Here's what's going on in the app:
              - There's a column in the DataGrid with an itemRenderer that contains the TextInput and Button.
              - Another column has an Image in its itemRenderer that displays the image just uploaded for that row.

              On the UPLOAD_COMPLETE_DATA event handler of the FileReference object, the app sets some custom properties (such as UploadedFileName) on the datagrid, and then call dataGrid.invalidateDisplayList() to force the set data() function in the itemRenderer.

              In the set data() of the image column, I check to see if the data.UploadedFileName is set; if so, the Image's source property is set to its name.

              So one column handles the upload (a button for Browse and a TextInput to show the file name selected). Another column displays the Image the user just uploaded.

              I'm lost as to how to do this according to good programming practices. I'm wide open to suggestions. Custom events were one way I thought could improve the OOP practices in the app. Thanks.
              • 4. Re: Setting component properties in itemRenderer
                JeffryHouser Level 4
                curious_lee,

                There are millions of ways to approach it while still keeping good programming practices.

                I don't inherently have any problem w/ your approach.

                But, I'd probably put the upload code in the itemrenderer and the update the data Object, which should in turn update the other column that displays the image.

                At least in theory that should work.
                • 5. Setting component properties in itemRenderer
                  ac361 Level 1
                  Hi, JeffHouser. I remember someone saying it's best to use custom events to communicate between an itemRenderer and the app. So I've been trying to write custom events. These events have private members for the controls I need to access from the main app and getter/setter methods for them as well. Then, in the main app, I can just say something like this,

                  private var ti:TextInput = new TextInput();

                  public function handleEvent(event:MyCustomEvent):void {
                  ti = event.myTextInput;
                  ti.text = "some text";
                  }

                  I have global variables in the app level code so that I can then reference the TextInput if I need to. I'm going to end up using a Model object, set it to reference the itemRenderer controls, and just pass it to the event and then reference the different controls within that from the main app.

                  But as you indicated, it might be good to just put the functions that are for that itemRenderer within its <mx:component> tag and set some custom properties on the data object.
                  • 6. Re: Setting component properties in itemRenderer
                    Level 7

                    "JeffHouser" <webforumsuser@macromedia.com> wrote in message
                    news:go6g9o$k4p$1@forums.macromedia.com...
                    > Amy,
                    > He said it was a custom event; unless he put it there it would not have
                    > reference to the itemRenderer.

                    All events contain a reference to the component that dispatched them, unless
                    they are dispatched from an eventDispatcher that was initialized with null
                    in the constructor. I strongly doubt the op is advanced enough to do that,
                    even by accident.


                    • 7. Re: Setting component properties in itemRenderer
                      Level 7

                      "curious_Lee" <webforumsuser@macromedia.com> wrote in message
                      news:go6mjt$rl5$1@forums.macromedia.com...
                      > Hi, JeffHouser. I remember someone saying it's best to use custom events
                      > to
                      > communicate between an itemRenderer and the app.

                      You might find this helpful:
                      http://flexdiary.blogspot.com/2007/08/dispatching-events.html

                      MPO is that using custom events when you don't need to (and you don't)
                      couples the application and the components too tightly, as both must import
                      the same custom class in order to establish communication.

                      > So I've been trying to write
                      > custom events. These events have private members for the controls I need
                      > to
                      > access from the main app and getter/setter methods for them as well. Then,
                      > in
                      > the main app, I can just say something like this,
                      >
                      > private var ti:TextInput = new TextInput();
                      >
                      > public function handleEvent(event:MyCustomEvent):void {
                      > ti = event.myTextInput;
                      > ti.text = "some text";
                      > }

                      Try:

                      public function handleEvent(event:MyCustomEvent):void {
                      //in this scenario ti is a global string variable that is receiving the
                      text
                      ti= (event.currentTarget as
                      YourRendererClass).publicallyExposedVarThatContainsTheTextValue;
                      /*Never try to directly set any property on a member of an
                      itemrenderer!!!
                      ti.text = "some text";
                      If you have to send something into the renderer, do it like this:*/
                      (event.currentTarget.data as
                      YourDataProviderElementType).columnYourTextInputIsBoundTo='foo';
                      }

                      HTH;

                      Amy


                      • 8. Re: Setting component properties in itemRenderer
                        JeffryHouser Level 4
                        Amy,

                        What you say makes sense; but have you tested that? It goes against my theories of encapsulation.

                        The property is there for Target and CurrentTarget on the event object; but if you don't set them yourself as part of the constructor; how are they set? Especially since they are read only properties.

                        http://livedocs.adobe.com/flex/3/langref/flash/events/Event.html

                        http://livedocs.adobe.com/flex/3/langref/flash/events/EventDispatcher.html#dispatchEvent()
                        • 9. Re: Setting component properties in itemRenderer
                          Level 7

                          "JeffHouser" <webforumsuser@macromedia.com> wrote in message
                          news:go708c$9r3$1@forums.macromedia.com...
                          > Amy,
                          >
                          > What you say makes sense; but have you tested that? It goes against my
                          > theories of encapsulation.

                          Sorry bout that :-). The good news is...you can absolutely revise your
                          theories to be more in line with how Flex works.

                          > The property is there for Target and CurrentTarget on the event object;
                          > but
                          > if you don't set them yourself as part of the constructor; how are they
                          > set?

                          They are set when the EventDispatcher for the component is set up...not the
                          Event itself. ALL UIComponents and classes that extend UIComponent extend
                          EventDispatcher, and because of that inheritance the target property is set
                          to the UIComponent that called dispatchEvent(). The way that currentTarget
                          gets set has to do with what component you called addEventListener on.

                          > Especially since they are read only properties.
                          >
                          > http://livedocs.adobe.com/flex/3/langref/flash/events/Event.html

                          Of course they're read-only at the event, because they aren't set by the
                          event class at all. They're set by the EventDispatcher component that
                          actually does the dispatching.


                          • 10. Re: Setting component properties in itemRenderer
                            JeffryHouser Level 4
                            Amy,

                            How do you quote previous messages?

                            I still holding onto my theories of encapsulation. A class w/ properties needs those properties in the class somehow; and that is completely independent of properties set on an unrelated event.

                            The target and currentTarget properties of the event class are read only. That means they cannot be set by an outside class. This has nothing to do w/ how the EventDispatcher is set up. There is no set method, so the EventDispatcher cannot go:

                            "event.target = some value"

                            The best guess at the moment is that there are protected (or mx_internal) methods which the EventDispatcher can call on the event class because they are part of the same package and the target / currentTarget methods are set as a side effect of those methods.

                            But that is different than the event dispatcher setting those properties. Since the code is part of the flash namespace, we probably can't go ahead and look.
                            • 11. Re: Setting component properties in itemRenderer
                              Level 7

                              "JeffHouser" <webforumsuser@macromedia.com> wrote in message
                              news:go757j$fos$1@forums.macromedia.com...
                              > Amy,
                              >
                              > How do you quote previous messages?
                              >
                              > I still holding onto my theories of encapsulation. A class w/
                              > properties
                              > needs those properties in the class somehow; and that is completely
                              > independent
                              > of properties set on an unrelated event.
                              >
                              > The target and currentTarget properties of the event class are read
                              > only.
                              > That means they cannot be set by an outside class. This has nothing to do
                              > w/
                              > how the EventDispatcher is set up. There is no set method, so the
                              > EventDispatcher cannot go:
                              >
                              > "event.target = some value"
                              >
                              > The best guess at the moment is that there are protected (or mx_internal)
                              > methods which the EventDispatcher can call on the event class because they
                              > are
                              > part of the same package and the target / currentTarget methods are set as
                              > a
                              > side effect of those methods.
                              >
                              > But that is different than the event dispatcher setting those properties.
                              > Since the code is part of the flash namespace, we probably can't go ahead
                              > and
                              > look.

                              Suit yourself. But as an experiment, create a data class that implements
                              IEventDispatcher, and then instantiate its EventDispatcher instance without
                              passing the parameter in its constructor. Now, create an instance of your
                              class and add an event listener for some event. Next, set a break point in
                              that handler, and see what you have for event.target.