Mediator to pass data to sub views

alebianco's Avatar

alebianco

06 Aug, 2015 08:06 PM

hi all,
I'm looking for a suggestion or a best practice about an architectural issue I've been struggling with lately.

I've a Model that contains an array of data.
This information has to be viewed as a list with a fixed number of elements, so I've a ContainerView and n ItemView that display each item. Both ContainerView and ItemView are mediated.

Ideally I'd like ItemMediator to set the relevant data into it's own view but that requires one of them to know their "position" to pick the rough stuff from the model, which I'm not too happy about.
Maybe the ContainerMediator should be responsible to set the data to his children and ItemMediator handles just the following user interactions? This kind of makes sense but requires a view to expose (or set data to) his children views. Also, this would probably be my favourite choice for a non-fixed size list of items.

I know there's no "right" solution that fits every situation, i'm more interested in the best practices and how other people solved similar problems.

Thanks all!

PS: a little background. I'm not using RL2 nor actionscript, but since it's my favourite framework, I've ported the key bits of it to Haxe while using a swiftsuspenders-like library as foundation for it. Basically it's pretty close to the real deal, probably with some extra but still for the added fun...

  1. Support Staff 1 Posted by Ondina D.F. on 07 Aug, 2015 10:10 AM

    Ondina D.F.'s Avatar

    Hi Alessandro,

    It's good to see you around!

    Maybe the ContainerMediator should be responsible to set the data to his children and ItemMediator handles just the following user interactions?

    I'm sure you didn't mean to set subview's data directly from mediator, something like:

    view.itemViewAtPositionOne.setSomeProperty(value);
    view.itemViewAtPositionTwo.setSomeProperty(anotherValue);

    where view is the ContainerView injected into ContainerMediator. This wouldn't be very nice.

    This kind of makes sense but requires a view to expose (or set data to) his children views

    This sounds like you certainly meant to set subviews' data inside of containerView, right?
    In my opinion, that could be just fine.

    Some very general rules for parent-child communication on a component level, when components aren't mediated:

    • parent accesses child's API

    • child dispatches events for the parent to hear

    Top to bottom through API, bottom to top through events.

    Now, in the world of mediated views, we want views to be as encapsulated as possible and that's why we try to let views communicate with each other via their mediators. And that's why it bothers you to access child-views directly from the parent-view, right?

    Ideally I'd like ItemMediator to set the relevant data into it's own view but that requires one of them to know their "position" to pick the rough stuff from the model, which I'm not too happy about.

    Why is itemView's data depending on view's position? Could you provide more details on this?
    Does ContainerView know about children's position? Are the children added dynamically?
    If they are added dynamically, can't you assign an ID for each added view?
    In the case of accessing ItemView's API, how is ContainerView deciding which data is meant for a certain ItemView? Is the position of one subview always the same?

    From what you said, I infer that the model keeps a map of view's data and their positions or maybe IDs. Is that so?
    Is ContainerMediator making a request for subviews' data or is ContainerMediator just listening for models events?
    Could a map of children's ids to their position - created when the subviews are added to the parent view - be of any use to you? ContainerMediator would send the map as a payload of the event that is requesting data from the model.
    Could each ItemMediator decide which data is meant for its view, if the model would dispatch events with an additional info about ids?

    Are the ItemViews similar from a layout point of view, having just different content? Or is their content and layout completely different and ContainerView is just presenting them as a kind of list. Or, is an ItemView more like an item renderer?

    If having each ItemMediator get the data for its own view turns out to be too complicated or convoluted, I'd opt for letting ContainerView provide subview's data.
    What about a view factory used inside of ContainerView that would encapsulate the logic of setting subviews' data?

    Hopefully others will have more suggestions for you, too, after you provide a bit more details.

    Ondina

  2. 2 Posted by alebianco on 10 Aug, 2015 01:20 PM

    alebianco's Avatar

    Hi Ondina,
    loads of good ideas here already, as always. Let see if I can give some extra details ...

    At a very high level, ContainerView acts as a list and you can consider ItemView as the renderer for the data of such list.
    The data is being loaded through a Service in a Command, triggered by a Signal triggered somewhere else. So both Container and Item only receive a notification of the data being changed. The data changes in blocks, a new Array of length N replaces the previous set of values.
    I have two separate cases, one where the N length is fixed and the other is dynamic. I could use the same generic ContainerView or make two specialised classes to optimise performances but I'd like to follow the same set of patterns for both cases. In both cases the items of the list are displayed in a very similar way.

    I think it would be reasonable to have the ContainerMediator to create the ItemViews and assign them an index, so that the ItemMediator could use it when the Model changes. This way everything related to the ItemView management would be contained in it's Mediator.

    One possible issue is that, in the fixed-N component, the ItemViews are created by a "third party" (a processor that parses a json file and creates the appropriate view classes) so the ContainerMediator would have to go through the childs after their creation and assign ids. An approach that could open the door to various issues potentially.

    We also thought to keep a map ID->ItemView in the ContainerMediator and generated after the views auto-creation. So that ContainerMediator would have to deal with setting the data while ItemMediator would deal only with user interactions. I don't dislike this but it didn't find the team's consensus.

    Hope this gives a bit more of context :)

  3. Support Staff 3 Posted by Ondina D.F. on 11 Aug, 2015 10:36 AM

    Ondina D.F.'s Avatar

    Thank you for providing more info:)
    I'm afraid that I won't be able to give you a concrete solution/suggestion, because the use case is still too abstract. But, I realize that you can't disclose much about your project.

    At a very high level, ContainerView acts as a list and you can consider ItemView as the renderer for the data of such list.

    If it is a list, why don't you implement the concept of a dataProvider in the ContainerView and the set data() in the ItemView? Even if it's not a regular list, you can implement a reduced functionality of a data provider in your ContainerView. Your ContainerView is the owner of those ItemViews, so it should be allowed to set their data.

    The data is being loaded through a Service in a Command, triggered by a Signal triggered somewhere else.

    I've a Model that contains an array of data. This information has to be viewed as a list with a fixed number of elements, so I've a ContainerView and n ItemView that display each item. Both ContainerView and ItemView are mediated.

    When you create the array/collection from the loaded data, you could also assign an id for each item. When an ItemView receives its data, it also receives an id, that it can use for further requests.

    One possible issue is that, in the fixed-N component, the ItemViews are created by a "third party" (a processor that parses a json file and creates the appropriate view classes) so the ContainerMediator would have to go through the childs after their creation and assign ids.

    I don't understand why a fixed length of ItemViews is a problem. There must be a reason for that, but I can't see it, and the additional info you provided doesn't make it more clear (at least not to me). Maybe you meant that an ItemView at a certain position in the list should always receive the same type of data? Like ItemView at position 0 gets a userImage, ItemView at position 1 gets user's name, age..., ItemView at position 2 gets a list of books that the user likes, etc ?

    The processor you are talking about would be something like a factory, in my understanding. If it creates the ItemViews classes dynamically, why can't it also pass views' data in the same process. Or at least create a map of indexes to ids to be stored in a model?

    We also thought to keep a map ID->ItemView in the ContainerMediator and generated after the views auto-creation.

    I wouldn't keep the map inside the Mediator or the View, but in a Model, probably in the same Model that is containing the collection of items' data. (I also wouldn't create or add subviews directly in the Mediator. That is View's responsibility.)

    In my mind you need a way to 'identify' the children, either by index or by an id of some sort.

    The map / dictionary of indexes to ids (or other criteria) can be created

    1 either by the Model or the factory (your 'processor') that creates the subviews ( Model->dictionary->View)
    2 or by the views themselves (View-> dictionary ->Model)

    For example, when ContainerView adds an ItemView, it also adds the child's index->id to a dictionary, and when it is done adding its children it dispatches an event/signal with the dictionary of registered children as a payload, so that a model can store that dictionary and use it to filter the view's data as needed.

    The data changes in blocks, a new Array of length N replaces the previous set of values.

    This would mean that if ContainerView were a regular List, when model's data changes, the list would simply refresh its dataProvider, and you wouldn't need to let each item request its data. It is again not clear to me why you need each ItemView to be able to request its own data when you deal with a fixed list length, but I'm sure there is a good reason for this.

    It also remains unclear if the criteria used for distributing the loaded data to the ItemViews are external to the application (an external id or name or something else), or are defined in the Model or in the ContainerView. I also still don't understand if the data presented by each ItemView has the same structure or not.

    I think this is important to know, because if for example the loaded data contains something like a userImageURL, userPersonalData, userPreferences, then it might be easy to create an ItemView that exhibits the behaviour of showing images (by implementing a IShowImages interface), another that implements an IPersonalData, etc. Their Mediators could add listeners to events/signals specific for view's role... This is pure speculation and it probably has little or no value for your concrete use case.

    I have two separate cases, one where the N length is fixed and the other is dynamic.

    So, the dynamic one works and you have trouble implementing the same logic to the fixed length one?
    Why can't you create a dynamic list with a fixed length?

    So that ContainerMediator would have to deal with setting the data while ItemMediator would deal only with user interactions. I don't dislike this but it didn't find the team's consensus.

    The ContainerView, not the ContainerMediator, would set its children's data. The ContainerMediator would just pass the data from the model to the ContainerView.
    What's your colleagues' argument against this?

    I have the feeling, that I can't help you much....

  4. Ondina D.F. closed this discussion on 28 Oct, 2015 03:50 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