Item Renderers - Injection and event handling

Daniel's Avatar

Daniel

13 Dec, 2009 08:51 PM

In my admittedly cursory look through the examples, searches on google
and the knowledge base, I'm coming up short on examples on how to
attach eventlisteners to an item renderer from the mediator. Any
thoughts?

  1. Support Staff 1 Posted by Shaun Smith on 13 Dec, 2009 09:38 PM

    Shaun Smith's Avatar

    If it's a custom item renderer, you could dispatch custom bubbling events. The mediator would then simply register listeners directly with the view component.

  2. Support Staff 2 Posted by Joel Hooks on 13 Dec, 2009 10:12 PM

    Joel Hooks's Avatar

    So you don't want to listen for events on item renderers... ever. Renderers should push events up through the list/grid that holds them. Custom events with the data as a payload.

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

    Item renderers are wacky. They recycle and are in a constant state of flux. You will reduce coupling and generally have better days if you treat them as totally contained and never try to listen or act on them directly from the outside.

    That said, you could simply bubble events up. I think this approach is poor. Hate bubbled events, especially in item renderers. Explicit ftw...

  3. 3 Posted by Tim Oxley on 13 Dec, 2009 11:25 PM

    Tim Oxley's Avatar

    I'm having a similar issue where I want to be able to inject a ResourceManager so i can use localisation on strings in my item renderers.

    So perhaps should just pretend to be not using Robotlegs in item renderers and use something like the built in Singleton ResourceManager.getInstance() business?

    I think the problem would be resolved if I could map a mediator to an item renderer, but that doesn't work either. Hmm

  4. Support Staff 4 Posted by Joel Hooks on 13 Dec, 2009 11:29 PM

    Joel Hooks's Avatar

    I think you are on the correct path with leveraging Flex's tools for getting the job done. If you wanted to build a cleaner way to accomplish this, then it would probably require ditching ResourceManager in favor of a system you developed. I'd just deal with the hand you are dealt and let Flex be Flex in these situations.

  5. 5 Posted by Tim Oxley on 14 Dec, 2009 12:46 AM

    Tim Oxley's Avatar

    Ahhhh, anyway, I just found a way around the problem and got the injection working perfectly: discovered the mapPackage/mapType functions (wasn't in docs at time of writing). This will allow injection to occur within your views, skins & item renderers without having to manually do injections (which was a pain to do for skins).

    The only real issue I was having was getting Flex to inject through all my view components. In fact I've been stressing over this for the past week (manually injecting into all my skin classes and whatnot) and am very relieved to have found such a simple solution. Thanks guys.

  6. 6 Posted by Daniel on 14 Dec, 2009 01:54 PM

    Daniel's Avatar

    Injection into Item Renderers

    Though I didn't really address it in my question, I did put it in the subject line. Since it looks like someone else posted a note about it, I will post my solution as well...

    Injecting the resourceManager into an item renderer:

    Summary: I've registered an IFactory with Robotlegs for the Injections.
    Howto:
    Implement mx.core.IFactory and return your item of choice

    public class DnsItemRendererFactory implements IFactory {
        //the property we want to inject into our item renderer
        [Inject]
        public var resourceManager:IResourceManager;
    
        //This method is called by the list to create a new instance of the renderer.  
        //We tell it what kind to make, and inject dependencies.  This all happens
        //before the item is rendered
        public function newInstance():*{
            var renderer:DnsItemRenderer = new DnsItemRenderer();
            renderer.resourceManager = resourceManager;
            return renderer;
        }
    }
    

    In your view/mxml add the following injectable var. The name attribute on the inject tag will help us to map this injection in the context.

    [Inject(name="dnsItemRendererFactory")]
    [Bindable]
    public var itemRendererFactory:IFactory
    

    Also in your view/mxml reference the factory in your list as the itemRenderer. Remember, if you just provide a class name here, flex just creates its own class factory. We are just providing the class factory directly:

    <mx:List
        dataProvider="{model.records}"
        itemRenderer="{itemRendererFactory}" />
    

    Finally, in your context:

    //map our resourceManager dependency
    injector.mapValue(IResourceManager, ResourceManager.getInstance());   
    //map our factory
    injector.mapSingletonOf(IFactory, DnsItemRendererFactory, "dnsItemRendererFactory");
    
  7. 7 Posted by levi.strope on 14 Dec, 2009 02:59 PM

    levi.strope's Avatar

    So would making a mediator for each itemRenderer a bad idea?

    That is currently what I'm doing.

  8. Support Staff 8 Posted by Joel Hooks on 14 Dec, 2009 03:15 PM

    Joel Hooks's Avatar

    Item renderers should be completely encapsulated, reacting to changes in their data property and dispatching events through their list/owner that interested components can react to.

    One thing many people try to do is access an itemRenderer from outside of the list. For example, you might want to make the cell in the fourth column of the fifth row in a DataGrid turn green because you've just received new data from the server. Getting that itemRenderer instance and modifying it externally would be a huge breech of the Flex framework and component model.

    I am in agreement with this statement. Accessing itemRenderers directly wreaks.

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

  9. 9 Posted by Daniel on 14 Dec, 2009 03:30 PM

    Daniel's Avatar

    @Joel - It appears that your comment was referencing Levi's question about using mediators for the item renderers. Is this the case?

  10. 10 Posted by levi.strope on 14 Dec, 2009 03:30 PM

    levi.strope's Avatar

    I agree that accessing them directly is dangerous, but if you mediate them with the understanding that each mediator will be 1 row in the list, you can get away with accessing it directly within the mediator can't you? You'd only get 1 mediator for each instance of the itemRenderer and the framework would handle the wiring.

    It's no different (conceptually) than having all that logic between script tags on your view, is it not?

  11. 11 Posted by Daniel on 14 Dec, 2009 03:37 PM

    Daniel's Avatar

    Ha! My example was flawed, forgot that mxml components already have a reference to resourceManager in them :-)

    It was a contrived example anyway. You could use this method to inject other properties as needed.

  12. Support Staff 12 Posted by Joel Hooks on 14 Dec, 2009 03:54 PM

    Joel Hooks's Avatar

    @levi It is a slippery slope that shatters the encapsulation of item renderers. They are probably the doggiest aspect of the entire Flex 3 framework (4 makes some great improvements here). You can get away with practically anything, whether it is a good idea or not. I'd never mediate item renderers and have always gone down the pitching events up the chain route with great success.

    @daniel yes, I was addressing Levi, but I would recommend against injecting into item renderers generally as well. They serve a purpose in Flex, to display (render) a single piece of data.

    Obviously your mileage may vary.

  13. 13 Posted by Tim Oxley on 15 Dec, 2009 12:28 AM

    Tim Oxley's Avatar

    @Daniel I am using a custom resource manager implementation so the the one provided by flex in the display classes doesn't help so much. I hadn't thought about or looked at the factories for item renderers before, and I guess this is what they are there for. Thanks for putting me onto that, though this mapPackage("com.***.views") style thing seems to just work.

    @joel I totally understand with your sentiment regarding item renderers just responding to the model. In my design, I'm allowing for strings on my model to be localized on the view tier as I don't feel this has any relevance to my model's functioning, so without some kind of injection (automatic or not) how else am I to access my global resource manager from the item renderer? or any other view-specific module?

    Now I'm thinking the alternative would be creating another layer of abstraction between the raw model and the view (the "view-model"?) which makes the necessary transformations ready for the view, so all the actual view does is simply display the provided data on the screen. The data comes from the "view-model" as opposed to the model directly. Also allows for more controlled information hiding on the raw model. That smells better to me, what do you think?

  14. Support Staff 14 Posted by Joel Hooks on 15 Dec, 2009 01:10 AM

    Joel Hooks's Avatar

    View-Model (aka Presentation Model) sounds like an excellent approach.
    Though, the Ent artcles I linked to describe creating a custom list/
    grid. You could mediate this and provide it with the dependency and
    access/supply the renderers the resource manager from there.

    this.resourceManager = this.list.resourceManager

  15. 15 Posted by Tim Oxley on 15 Dec, 2009 02:25 AM

    Tim Oxley's Avatar

    Yes presentation model is exactly what I had in mind. Thanks Joel. http://martinfowler.com/eaaDev/PresentationModel.html

  16. Support Staff 16 Posted by Joel Hooks on 15 Dec, 2009 03:07 AM

    Joel Hooks's Avatar

    Ah good, you found the Fowler article. I woulda linked it but was on my phone ;)

  17. 17 Posted by Andrei TT on 29 Dec, 2009 06:52 PM

    Andrei TT's Avatar

    So far in my Flex projects i've only used Joel's approach of dispatching a bubbling custom Event with the data from the item renderer. ( i also once accessed methods directly on a singleton controller class from the item renderer but i think that goes into very-bad-practices idea).
    The Presentation Model idea is interesting though.

  18. Till Schneidereit closed this discussion on 02 Mar, 2010 12:55 PM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac