MyConfig.configure() not getting called.

Joel Stransky's Avatar

Joel Stransky

16 Nov, 2012 12:24 PM

Hi guys, trying a simple hello world to get a feel for RL2 today. Feels very different from RL1 so I'm a little lost. I'm not getting a trace from HelloConfig.configure. What gives?

Main class

package
{
    import flash.display.Sprite;
    public class RL_Hello extends Sprite
    {
        private var _app:HelloApp;
        public function RL_Hello()
        {
            trace("RL_Hello");
            _app = new HelloApp();
            addChild(_app);
        }
    }
}

HelloApp.as

package
{
    import flash.display.Sprite;
    
    import robotlegs.bender.framework.api.IContext;
    import robotlegs.bender.framework.impl.Context;
    import robotlegs.bender.bundles.mvcs.MVCSBundle;
    
    public class HelloApp extends Sprite
    {
        private var _context:IContext;
        public function HelloApp()
        {
            trace("HelloApp");
            _context = new Context()
                .install(MVCSBundle)
                .configure(HelloConfig, this);
        }
    }
}

HelloConfig.as

package
{
    import flash.display.DisplayObjectContainer;
    
    import robotlegs.bender.extensions.mediatorMap.api.IMediatorMap;
    import robotlegs.bender.framework.api.IConfig;
    import robotlegs.bender.framework.api.IContext;
    import robotlegs.bender.framework.api.LogLevel;

    public class HelloConfig implements IConfig
    {
        [Inject]
        public var context:IContext;
        
        [Inject]
        public var mediatorMap:IMediatorMap;
        
        [Inject]
        public var contextView:DisplayObjectContainer;
        
        public function configure():void{
            trace("HelloConfig.configure");
            context.logLevel = LogLevel.DEBUG;
            mediatorMap.map(HelloView).toMediator(HelloMediator);
            context.lifecycle.afterInitializing(init);
        }
        
        private function init():void{
            trace("HelloConfig.init");
            contextView.addChild(new HelloView());
        }
    }
}
  1. Support Staff 1 Posted by Ondina D.F. on 16 Nov, 2012 01:37 PM

    Ondina D.F.'s Avatar

    Hi Joel,

    I do the configuration like this:

    MainView.as

    package
    {
        import flash.display.Sprite;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        import flash.events.Event;
        import flash.text.TextField;
    
        import yourdomain.config.ApplicationContext;
        import yourdomain.views.components.HelloView;
    
        public class MainView extends Sprite
        {
            private var context:ApplicationContext;
    
            public function MainView()
            {
                stage.align = StageAlign.TOP_LEFT;
                stage.scaleMode = StageScaleMode.NO_SCALE;
                addEventListener(Event.ADDED_TO_STAGE, onViewAdded);
            }
    
            protected function onViewAdded(event:Event):void
            {
                trace("ContextView.onViewAdded(event)");
                context = new ApplicationContext(this);
                createChildren();
            }
    
            public function createChildren():void
            {
                trace("ContextView.createChildren()");
                var myText:TextField = new TextField();
                myText.x = 10;
                myText.width = 400;
                myText.text = "MAIN VIEW";
                addChild(myText);
    
                var helloView:HelloView = new HelloView();
                helloView.x = 10;
                helloView.y = 100;
                addChild(helloView);
            }
        }
    }
    

    ApplicationContext.as

    package yourdomain.config
    {
        import flash.display.DisplayObjectContainer;
    
        import org.swiftsuspenders.Injector;
    
        import robotlegs.bender.bundles.mvcs.MVCSBundle;
        import robotlegs.bender.extensions.eventCommandMap.api.IEventCommandMap;
        import robotlegs.bender.extensions.logging.InjectorLoggingExtension;
        import robotlegs.bender.extensions.mediatorMap.api.IMediatorMap;
        import robotlegs.bender.framework.context.api.IContext;
        import robotlegs.bender.framework.context.impl.Context;
    
        import yourdomain.views.components.HelloView;
        import yourdomain.views.mediators.HelloMediator;
        import yourdomain.views.mediators.MainMediator;
    
        public class ApplicationContext
        {
            private var injector:Injector;
            private var mediatorMap:IMediatorMap;
            private var commandMap:IEventCommandMap;
            private var context:IContext;
            private var _contextView:DisplayObjectContainer;
    
            public function ApplicationContext(contextView:DisplayObjectContainer = null, autoStartup:Boolean = true)
            {
                trace("ApplicationContext.ApplicationContext(contextView, autoStartup)");
    
                context = new Context();
                context.extend(MVCSBundle, InjectorLoggingExtension);
                //context.logLevel=LogLevel.DEBUG;
                context.configure(contextView);
                _contextView = contextView;
                injector = context.injector;
                mediatorMap = injector.getInstance(IMediatorMap);
                commandMap = injector.getInstance(IEventCommandMap);
    
                mapMappingCommands();
            }
    
            private function mapMappingCommands():void
            {
                trace("ApplicationContext.mapMappingCommands()");
                //usually,I do the mappings in separate commands
                mediatorMap.mapView(HelloView).toMediator(HelloMediator);
                mediatorMap.mapView(MainView).toMediator(MainMediator);
                mediatorMap.handleView(_contextView, MainMediator);
            }
        }
    }
    

    Does that help?
    Ondina

  2. Support Staff 2 Posted by Shaun Smith on 16 Nov, 2012 02:34 PM

    Shaun Smith's Avatar

    In the latest version you have to supply the view wrapped in a ContextView object. I think I updated all the readmes, but it's possible that I missed some.

    .configure(new ContextView(this))

    Shaun Smith
    http://twitter.com/darscan
    http://shaun.boyblack.co.za

  3. 3 Posted by Joel Stransky on 16 Nov, 2012 05:09 PM

    Joel Stransky's Avatar

    Thanks for the example Ondina. It always helps understand intent when I see things used differently. For now I want to address Shaun's comment first and then I'll contemplate a different structure.

    @Shaun, here's my updated bootstrap:

    public class HelloApp extends Sprite
        {
            private var _context:IContext;
            public function HelloApp()
            {
                trace("HelloApp");
                _context = new Context()
                    .install(MVCSBundle)
                    .configure(HelloConfig)
                    .configure(new ContextView(this));
            }
        }
    

    but now I get an injector error.
    Error: Injector is missing a mapping to handle injection into property "contextView" of object "[object HelloConfig]" with type "HelloConfig".

    I'm not sure how to handle that mapping.

  4. 4 Posted by Joel Stransky on 16 Nov, 2012 05:51 PM

    Joel Stransky's Avatar

    I'm borrowing this approach from https://github.com/darscan/robotlegs-demos-HelloFlash by the way.

  5. Support Staff 5 Posted by Ondina D.F. on 16 Nov, 2012 06:58 PM

    Ondina D.F.'s Avatar

    This works:

    View

    _context = new Context()

    .install(MVCSBundle)

    .install(ContextViewExtension)

    .configure(AppConfig)

    .configure(new ContextView(this));

    AppConfig.as

    [Inject] public var contextView:ContextView;

    //===contextView type is ContextView !!!

    …..

    private function init():void
    {

    // add the view that has the mediator mapped to it

    contextView.view.addChild(new MessageWriterView());

  6. Support Staff 6 Posted by Shaun Smith on 16 Nov, 2012 07:21 PM

    Shaun Smith's Avatar

    Ah yes, I'll need to update those examples. The ContextView is mapped into the injector as ContextView. Inject that and you can access the wrapped view object.

    It may seem like a bit of a silly change, but mapping a raw DisplayObjectContainer directly into the injector always felt odd and unclear to me. The new way is much more explicit I think. Also, the whole context.configure(this) thing was super unclear.

  7. 7 Posted by Joel Stransky on 16 Nov, 2012 07:22 PM

    Joel Stransky's Avatar

    Sorry if this triple posted. I'm not seeing this thread update.

    I thought that the MVCSBundle already installed ContextViewExtension.
    Changing the type to ContextView worked. It seems redundant to have to say contextView.view

    So now the only problem is, the event I dispatch from my view constructor is not being caught by its mediator.

    HelloView.as

         private var _tf:TextField;
            public function HelloView()
            {
                super();
                trace("HelloView()");
                _tf = new TextField();
                _tf.text = "Hello World";
                addChild(_tf);
                dispatchEvent(new HelloViewEvent(HelloViewEvent.HELLO));
            }
    

    HelloMediator.as

     public class HelloMediator extends Mediator
        {
            
            [Inject]
            public var view:HelloView;
            
            public function HelloMediator()
            {
                super();
            }
            
            override public function initialize():void{
                addViewListener(HelloViewEvent.HELLO, handleHello, HelloViewEvent);
            }
            
            private function handleHello(event:HelloViewEvent):void{
                trace("Hello View Event Detected");
            }
        }
    
  8. 8 Posted by Joel Stransky on 16 Nov, 2012 07:32 PM

    Joel Stransky's Avatar

    Ok, got the mediator to catch it but had to move to the dispatch to onAddedToStage. I wouldn't normally dispatch within the constructor anyway but I'm just hacking at the moment to see how the parts work together.
    Not sure if it means anything but at first I didn't remove the ADDED_TO_STAGE listener within onAddedToStage as is common and my event got handled twice in the mediator. Once I added the remove it worked as expected but I'm curious as to why that happened.

    See, this is why I love robotlegs so much. From this extremely basic example, I already feel like I could dive into a large app.

  9. Support Staff 9 Posted by Shaun Smith on 16 Nov, 2012 07:42 PM

    Shaun Smith's Avatar

    Yup, I imagine that your custom event was being fired too soon (a view object must be constructed before it can be parented). Not sure about the double added-to-stage though - that's a weird one.

    The ContextViewExtension is indeed installed by the MVCSBundle - it's job is to watch the configure() method for a ContextView object and map it into the injector:

    https://github.com/robotlegs/robotlegs-framework/blob/master/src/ro...

    Similarly, the StageSyncExtension inspects ContextView objects and auto initializes the Context:

    https://github.com/robotlegs/robotlegs-framework/blob/master/src/ro...

  10. Support Staff 10 Posted by Ondina D.F. on 20 Nov, 2012 10:14 AM

    Ondina D.F.'s Avatar

    Joel, this seems to be resolved. If you want to continue this discussion, feel free to reopen it.

  11. Ondina D.F. closed this discussion on 20 Nov, 2012 10:14 AM.

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