injecting event into command doesnt work

iamable's Avatar

iamable

07 Oct, 2014 11:35 AM

hey, i'm working the first time on robotlegs 2 and trying to inject an event into the command.
without injectiing that event the command is executed.

withoud event injection the code looks like that

view:
var myEvent:ButtonEvent = new ButtonEvent(ButtonEvent.CLICKED);
myEvent.id = this.identifier;
dispatchEvent(myEvent);

mediator:
addViewListener(ButtonEvent.CLICKED, dispatch);

config:
commandMap.map(ButtonEvent.CLICKED).toCommand(DoSomething);

this is working pretty well, but when I try to inject ButtonEvent into the command I get following error:
Error: Injector is missing a mapping to handle injection into property "event" of object "[object DoSomething]" with type "org.example.robotlegs::DoSomething". Target dependency: "org.example.robotlegs.views.button::ButtonEvent|"

so I changed the Config to:
commandMap.map(ButtonEvent.CLICKED, ButtonEvent).toCommand(DoSomething);
Now no error occurs but the command is never executed

Any suggestions? Thanks

  1. Support Staff 1 Posted by Ondina D.F. on 07 Oct, 2014 12:42 PM

    Ondina D.F.'s Avatar

    Hi,

    You need to override the clone() method in your custom event class, so it can be re-dispatched by the mediator.
    Have you done this?

    Ondina

  2. 2 Posted by iamable on 07 Oct, 2014 12:44 PM

    iamable's Avatar

    I did.

    public function ButtonEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false)
    { super(type, bubbles, cancelable); }

        override public function clone():Event
        {
            return super.clone();
        }
    
  3. Support Staff 3 Posted by Ondina D.F. on 07 Oct, 2014 12:50 PM

    Ondina D.F.'s Avatar

    It should look like this:

    public function CustomEvent (type:String, someData:yourType)
    {
        super(type);
                
    }
    public override function clone ():Event 
    {
        return new CustomEvent(type, someData);
    }
    
  4. 4 Posted by iamable on 07 Oct, 2014 01:15 PM

    iamable's Avatar

    oh sorry. used the wrong template ;-/

    thank you.

    I have another question under another topic:
    regarding AS3-Signals: how does it work to replace all my events with that signals?

    for example the simple button event:

    view:
    public var onClicked:Signal = new Signal();
    private function buttonClicked():void
    { onClicked.dispatch(); }

    mediator:
    [Inject] public var view : ButtonView;

        public function ButtonMediator()
        {
    
        }
    
        override public function initialize():void
        {
            view.onClicked.add(output);
        }
    
        private function output():void
        {
            trace("mediator: button clicked");
        }
    
  5. 5 Posted by iamable on 07 Oct, 2014 01:15 PM

    iamable's Avatar

    unfortunately this doesnt work

  6. 6 Posted by iamable on 07 Oct, 2014 01:20 PM

    iamable's Avatar

    oh sorry I was to fast with posting. I got it working now and I found the signal command mapping library for a nice integration within robotlegs.
    I will have a try

  7. Support Staff 7 Posted by Ondina D.F. on 07 Oct, 2014 01:24 PM

    Ondina D.F.'s Avatar
  8. Support Staff 8 Posted by Ondina D.F. on 07 Oct, 2014 01:26 PM

    Ondina D.F.'s Avatar

    Oh, now I see your other posts;)

    I guess then, this is resolved, right?

  9. 9 Posted by iamable on 07 Oct, 2014 01:29 PM

    iamable's Avatar

    one more thing:

    How can I redispatch received signal from the view?

    view.onClicked.add(output);

  10. 10 Posted by iamable on 07 Oct, 2014 01:35 PM

    iamable's Avatar

    do I really need another signal?

  11. 11 Posted by iamable on 07 Oct, 2014 02:08 PM

    iamable's Avatar

    and where do I find a current swc for the signalCommandMap library.
    I only find sources

  12. Support Staff 12 Posted by Ondina D.F. on 07 Oct, 2014 02:22 PM

    Ondina D.F.'s Avatar

    do I really need another signal?

    There is no 're-dispatch' functionality with signals. They work differently than events.

    So, the answer is yes. Of course, it is possible to dispatch a signal from a View that would trigger a command directly, in other words, without going through a Mediator. But, I wouldn't recommend this approach !! Since you're using the Mediator pattern, let it do its work:)

    and where do I find a current swc for the signalCommandMap library. I only find sources

    This is the only link I know:
    https://github.com/robotlegs/robotlegs-extensions-SignalCommandMap

    Sadly, there isn't an swc.

  13. 13 Posted by iamable on 07 Oct, 2014 02:24 PM

    iamable's Avatar

    and how does the command mapping work?

    the mediators does this:

    override public function initialize():void
    { anyButtonClicked = new Signal();

            view.onClicked.add(output);
        }
    
        private function output():void
        {
            anyButtonClicked.dispatch();
        }
    
  14. 14 Posted by iamable on 07 Oct, 2014 02:39 PM

    iamable's Avatar

    It seems to be much more complicated than events in robotlegs.
    I found this example:
    https://github.com/pixels4nickels/robotlegs-examples-SignalCommandM...

    now I dont have to create custom events but I have to create Trigger classes extending Signal.
    So where is the advantage?

  15. Support Staff 15 Posted by Ondina D.F. on 07 Oct, 2014 02:39 PM

    Ondina D.F.'s Avatar

    Please study the example mentioned above. Look at other examples listed under Resources and Examples for rl1 and rl2, as well.
    Look at Joel's tutorial, even if it is for rl1:
    http://joelhooks.com/2010/01/16/robotlegs-image-gallery-example-usi...

    Also, read through the discussions on this forum. Search for 'signalcommand':
    http://knowledge.robotlegs.org/search?q=signalcommand&recent=1&...

    I don't have the time to introduce you to signals :)

    If you want to know the inner working of the SignalCommandMap take a look at the tests:

    https://github.com/robotlegs/robotlegs-extensions-SignalCommandMap/...

  16. 16 Posted by iamable on 07 Oct, 2014 02:46 PM

    iamable's Avatar

    ok thank you

  17. 17 Posted by iamable on 08 Oct, 2014 09:55 AM

    iamable's Avatar

    Hello Ondina,

    I got my example running with signals.
    my architecture is looking as follows:

    I have a view button and a ClickedMediator passing the OnSelected signal to the button.
    This signal is mapped to a comand which changes an id within a model.
    when this id changes an OnChanged signal is dispatched. in another mediator (ChangeViewMediator) of the view there is a listener for that signal and changing the view regarding the id passed by the OnChanged signal.
    Thats working pretty fine.

    Now I would like to have some more buttons. Now when I press one of them all the buttons get changed. Could you please tell me how to structure for only changing the clicked button?
    maybe i can pass a reference of the clicked button to the OnSelected signal, write it from the command to the model and pass it again to the OnChanged signal and within the ChangeViewMediator I can change only this passed view. But this seems very complex. Is there another way?

    and one step further: is it possible to have a different model for every button so the id is exclusive for a single button?

  18. 18 Posted by iamable on 08 Oct, 2014 11:16 AM

    iamable's Avatar

    here is the config

    [PostConstruct] public function configure():void { injector.map(OnColorChanged).asSingleton();

            injector.map(Model).asSingleton();
    
            commandMap.map(OnSelected).toCommand(ChangeColor);
    
            mediatorMap.map(IButton).toMediator(SignalProvider);
            mediatorMap.map(IColorChange).toMediator(ColorChanger);
        }
    
  19. Support Staff 19 Posted by Ondina D.F. on 08 Oct, 2014 12:05 PM

    Ondina D.F.'s Avatar

    Hello,

    Not sure that that's the reason for your issue, because I can't see your application, but I think that you followed Peter's example and created a base view for your different buttons implementing the same interface. Then you mapped the interface to a mediator.
    If you have different mediators for each view, implementing the same interface, then you might want to map them like this:

    mediatorMap.mapMatcher(  
        new TypeMatcher().allOf(IView,  SomeView))
        .toMediator(SomeMediator);
    mediatorMap.mapMatcher(  
        new TypeMatcher().allOf(IView,  AnotherView))
        .toMediator(AnotherMediator);
    

    You might have a good reason for having each button mediated separately.
    However, I would solve this differently, by having a View containing the buttons, let's call it MenuView for the purpose of an example, and a MenuMediator, that would listen for signals from the MenuView when one of the buttons was clicked. Think of those buttons as of a list. Would you mediate each item in the list? Probably not. The selected item in a list, or in your case the clicked button, would have an event handler, where you'd dispatch a signal with the data you need to be 'transported' to the Model.

    Now I would like to have some more buttons. Now when I press one of them all the buttons get changed.

    What do you mean by that? I thought the ChangeView is the one "changing" when the model dispatches the change signal.

    How are you listening for the signal from the views, and how are you dispatching signals from your mediators?

    It's difficult to say what's going wrong without seeing more code.
    Could you attach your little example, so I can take a look at it?

    Ondina

  20. 20 Posted by iamable on 08 Oct, 2014 12:31 PM

    iamable's Avatar

    the problem I am pointing to is what if i have an object instantiated several times. each instance has the same behavior rules and states. for example a chess game. each pawn has the same behavior. the model for each pawn holds for example the position. Then there are different signals for the different moves mapped to a command which calculates the new psotion to be stored within the model. then there should be an position update signal which will trigger the views update.

    (I hope I understand robotlegs and signals and OOP in the right way ^^)

    In my application (attached) I added a flag to every view wether is is clicked or not. In the above example the picked pawn. only the selected one will be updated with the models new position. But now every pawn should have its own model. I dont know how to realize that

  21. Support Staff 21 Posted by Ondina D.F. on 08 Oct, 2014 12:58 PM

    Ondina D.F.'s Avatar

    o.k. I've dl-ed your app and will take a look at it later today. I'll let you know about my findings.

  22. 22 Posted by iamable on 08 Oct, 2014 01:00 PM

    iamable's Avatar

    thank you

  23. Support Staff 23 Posted by Ondina D.F. on 08 Oct, 2014 03:28 PM

    Ondina D.F.'s Avatar

    In the chess example, you don't need 16 or 32 Models! Really! What you want to have are VOs (value objects) that you are manipulating in a single Model. There is a difference between a Model and a VO. A VO is a container for values. You can use it to transport data between different actors. A Model can manipulate the VOs and can also make some calculations, if need be. A Model holds a collection of VOs, and accesses them based on some criteria, for example IDs. There is much more to say about the roles of Models and VOs, but that's for you to find out by reading through discussions, best practices or the rl book.

    So, a chess piece would have a corresponding VO, with an ID, a position and whatever else.
    Look at Joel's Gallery demo:

    https://github.com/joelhooks/robotlegs-examples-FlickrGallery/tree/...

    maybe i can pass a reference of the clicked button to the OnSelected signal, write it from the command to the model and pass it again to the OnChanged signal and within the ChangeViewMediator I can change only this passed view. But this seems very complex. Is there another way?

    Well, using views ids to differentiate between them is better than having 32 Models! It would be very cumbersome to access the right model in a single command and to find out which model corresponds to which view.
    One Model could generate 32 VOs with the ids coming from views. You could use that viewID in your view as well, to know which view has to change in response to the signal dispatched from Model. Or, as you did, using that flag of yours.
    I still think that you also don't need a mediator for each button, but that's not as bad as having as many Models.

    On a side note, in your ColorChanger (mediator) you inject ButtonView. Since you mapped it as an interface, why don't you inject the interface(IColorChange).
    You use another Mediator just to set the signal on the views. You could do the same inside of the ColorChanger, but you probably wanted SignalProvider to do more in the future, so maybe it was on purpose to separate behaviours.
    I've also noticed that you trigger the command directly from the view ;)

    Stray's demo might give you some hints on using VOs in Models and Views( some of them being many little tiles) :

    https://github.com/Stray/robotlegs-examples-OreillyBook/tree/master...

    I don't know if you know about entity systems like Ember, Ember2, XEmber. Maybe your application would be better off, if you used something like that? Maybe not. You'll have to decide depending on the nature of your app.
    But, please, don't ask me how to use such an entity framework ;)

  24. 24 Posted by iamable on 09 Oct, 2014 06:50 AM

    iamable's Avatar

    Thanks for your reply. I will have a look on VOs and the examples.
    The example with that chess pieces was just a structural example. For that little chess piece I wouldnt create a model for each of them.
    But what if I have an object with tons of data. so I would need a model for each of them.
    I just want to know how to handle that. I dont have a concrete example for that.

  25. Support Staff 25 Posted by Ondina D.F. on 09 Oct, 2014 10:59 AM

    Ondina D.F.'s Avatar

    You're welcome.

    But what if I have an object with tons of data. so I would need a model for each of them.

    You don't need a Model for each of them! As I said, you need VOs to represent your objects, and one Model that manipulates/stores the VOs .
    Here again, the list example: if you had a list with 1001 items, you wouldn't create a Model for each item. Each item would be represented by a ListItemVO, and a ListModel would than work with these ListItemVOs. The FlickrGallery demo illustrates this very nicely.

    Think of VOs as rows/records in a database table and of Models as the tables. You wouldn't create a new db table for each image! A single Images table would have 0-n images records. Each record would have 'properties', aka columns, like imageID, imageURL, imageName and so on.

  26. 26 Posted by iamable on 09 Oct, 2014 12:21 PM

    iamable's Avatar

    Sorry for jumping between topics. There is in addition another question just coming up:

    I try to unit test a model extending actor (RL1).
    The unit test is always failing since I am dispatching an event at the end of calculating a value.
    This event is just for updating the view with the result. so the unittest doesnt have to wait for async response. so why dispatch(event) doesnt work? if I am instatiating EventDispatcher and using eventDispatcher.dispatchEvent(event) it works. why? what to do to pass the unit test with robotlegs framework?

  27. Support Staff 27 Posted by Ondina D.F. on 09 Oct, 2014 12:45 PM

    Ondina D.F.'s Avatar

    That's correct, you need to provide an instance of an eventDispatcher, as you did.

  28. 28 Posted by iamable on 09 Oct, 2014 12:56 PM

    iamable's Avatar

    but Actor is providing that eventDispatcher...why this doesnt work?

  29. Support Staff 29 Posted by Ondina D.F. on 09 Oct, 2014 01:14 PM

    Ondina D.F.'s Avatar
  30. Ondina D.F. closed this discussion on 29 Oct, 2014 11:42 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