Separating of view creation and filling it with data

Luken's Avatar

Luken

10 Jun, 2012 12:12 AM

Hello!
It's probably a simple question, yet I wasn't able to find a clear answer and I'm quite a noob besides >_<. As in the title, I have a one parent view that contains a few children, that are dynamically created (so they may or may not to be needed in a single run of an application, they also may be of various types based on what loader service will provide). I would like to be able to create a child view only when it is needed, but I have a problem how to adopt a typical Robotlegs flow to that. Normally the mediator fills view with data, but in my case, the view and mediator doesn't exist yet, when user will click a button. So the child view, cannot get that loaded data at first click. The parent view however can catch proper event, use it as a signal for creating a child view and pass the data instantly to it. It would be nice but is it a right approach? I feel that would make a code less clear, as I will be listening for the same events in parent view and children. Parent will use it to create smaller ones and then would remove a listener, but what if the child-view needs to disappear? Or is not useful anymore? The parent would need to add his listeners once more so it could be able to create a smaller views once more if they would be needed. I can imagine that it can be quite a mess. So the question is - what is a best approach for such a simple goal as creating new views and filling it with data?

Regards!

  1. 1 Posted by Luken on 10 Jun, 2012 06:57 PM

    Luken's Avatar

    It would be best if anyone would have any examples of projects with dynamically created views of different types and filling them with data, after certain events. I just cannot imagine it overall. Where to put a factory etc. :/

  2. 2 Posted by Amy on 12 Jun, 2012 12:28 AM

    Amy's Avatar

    When a View is created, it can receive injections as soon as you add it to the stage. You set this up by adding the Class of the View that you will instantiate to the ViewMap. RobotLegs watches for it to be added, and it will provide its dependencies with any other information you've mapped in the Injector.

    Mediators are automatically created in the same way. So it doesn't matter if your Views are created dynamically or not. That's the whole point of Robotlegs.

    What have you tried, and what specific issues are you having

  3. 3 Posted by Luken on 12 Jun, 2012 07:45 AM

    Luken's Avatar

    I know, but the problem is that in the normal flow the click on UI element, will call a loader, that will change a value on the proper model, but now - the view doesn't exist yet, so it cannot get information about first model update. I can use that event (click) for creating that view, but I need to put somehow the data related to that click into the view as well. I have several options to do that and I'm not sure what is best.

    1. I can just put the data in the constructor of the view,
    2. I can send from just created view a request to its model, so it will send me the data it got from click once more.

    And I'm wondering what would be the best approach.

    First seems more natural, but what if I want to "cache" view at some point, so I removed it from display list and later I need to update it after showing it again? I would need to send a request for data anyway. And second doesn't look too clear. I hope that I put it clear, sorry if my considerations are chaotic :) .

    Regards.

  4. 4 Posted by Amy on 12 Jun, 2012 12:34 PM

    Amy's Avatar

    The best approach is "neither." Views should NOT be responsible for retrieving their own data. That data should be retrieved somewhere else, preferably in a separate service layer that will then spawn off one or more Commands to update the Model.

    If you do it in a more robust, best-practice way as I've suggested, you then have the option to reuse your Views or not--it really doesn't matter, since they will always receive the most up-to-date data.

    I know it gets confusing when you have examples like Adobe's "generated service" examples, which nearly always have these things handled in the View. But those examples are more what you'd do if you were dashing off a quick prototype, not something you can build on for full production code.

  5. 5 Posted by Abel de Beer on 13 Jun, 2012 02:50 PM

    Abel de Beer's Avatar

    Luken,

    I would recommend against passing the data through the constructor. Generally you're more flexible when using the Mediator's onRegister and onRemove methods to populate its view. The easy (and dirty) way would be to inject the Model into the Mediator, but a more loosely coupled way is what Stray once coined as the Request-Provide Pattern:

    If you're using Events, the process is rather straightforward: Create a custom event class, i.e. ViewDataProviderEvent, with a REQUEST and PROVIDE string constant. Make sure you also add a (preferably strongly typed) data property. In your Context's startup method, map ViewDataProviderEvent.REQUEST to i.e. ProvideViewDataCommand. Inject your Model into the ProvideViewDataCommand, and in its execute method you dispatch ViewDataProviderEvent.PROVIDE, along with the Model data. Now in your Mediator's onRegister method, add a listener for ViewDataProviderEvent.PROVIDE which populates your view using the data that is passed with the event. Lastly, dispatch a ViewDataProviderEvent.REQUEST event from the onRegister method.

    If you're using Signals, you'll be using a (request data) signal that accepts and dispatches a (provide data) signal: Create a custom Signal class, i.e. RequestViewDataSignal, and add super(Signal) to its constructor. In your Context's startup method, use the signalCommandMap to map the RequestViewDataSignal class to i.e. ProvideViewDataCommand (don't use the previous one :P ). Inject your Model into the ProvideViewDataCommand, and also inject a signal, i.e. provideViewData, with type Signal (should be the same type as the one you added to the RequestViewDataSignal constructor). In the ProvideViewDataCommand's execute method you dispatch the provideViewData signal, passing along the Model's data as its argument. Inject the RequestViewDataSignal in your Mediator. In its onRegister method, create a new Signal, i.e. provideData, with the Model's data type (maybe Array, or a VO) as its argument. Add a listener to this Signal which accepts the data type and populates your view. Lastly, dispatch the RequestViewDataSignal instance from the onRegister method, passing along the provideData signal as its argument.

    Try and experiment a bit and see which you prefer. Just come back here if you need more help.

    Abel

  6. Ondina D.F. closed this discussion on 14 Aug, 2012 05:47 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