Futurescale, Inc. PureMVC Home

The PureMVC Framework Code at the Speed of Thought


Over 10 years of community discussion and knowledge are maintained here as a read-only archive.

New discussions should be taken up in issues on the appropriate projects at https://github.com/PureMVC

Pages: [1]
Print
Author Topic: Mediators and their ViewComponent  (Read 8412 times)
4ucai
Jr. Member
**
Posts: 17


View Profile Email
« on: December 07, 2011, 10:41:11 »

Hello everyone,

I've read some post here regarding mediators and components. However, i want to know more something specific.

Basically, I have a panel view with child views
The panel view is a movieclip which is mediated by "PanelMediator"..
This is in StartupCommand:
:
// Create and Register the Application and its Mediator.
var app:PanelView= note.getBody() as Shell;
facade.registerMediator(new PanelMediator(app));

Then i had the child views given a mediator, say "SomeChildMediator" passing the component.
This is in PanelMediator:
:
override public function onRegister():void
{
   facade.registerMediator(new SomeChildMediator(panelView.child_mc));
}

private function get panelView():PanelView
{
 return viewComponent as PanelView;
}

Now, I add mouse event to the child view component(note the child view also contains related views).
This is in SomeChildMediator:
:
override public function onRegister():void
{
   chilView.btn1.addEventListener(MouseEvent.Click, onBtn1Click);
}

private var onBtn1Click(e:MouseEvent):void
{
   //show an btn background, can i do this?
  //childView.btn1.background.visible = true;
}

private function get childView():MovieClip
{
 return viewComponent as MovieClip;
}
I get that the component or module should encapsulate most of its state and behavior and
exposing only an api, which would look like this(if I'm not mistaken).
:
PanelView.doSomething();
However, Should "SomeChildMediator" directly change the state? Since it is only mediating the child view of
panelview, which i dont have a class of ChildView.as like PanelView.as. Also i will be dealing with a complex
panel or toolbar soon with lots of buttons(toggle state, some animation).  ???

Thanks in advance........
 


Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #1 on: December 08, 2011, 08:43:43 »

Avoid 'reaching into' that panel and setting listeners on its children or updating their state. Instead of placing a listener on the button, make the button dispatch a bubbling event and have the Mediator listen for the event on the view component. And if need be, call a method on the view component to affect its state rather than 'reaching in' and changing something. Otherwise, the Mediator knows too much about the implementation of the view component, which means it will usually have to be refactored if you change things inside the view component.

In the example below, note that the event coming out of the view component has some semantic meaning beyond just being the click event that came from some button. The Mediator is immediately able to operate at a higher level, dealing with user intentions not the nitty gritty details of the componentry. This makes the Mediator more understandable, which is what you want at the framework level.

:
override public function onRegister():void
{
  childView.addEventListener(AppEvent.SUBMIT_FORM, onSubmitForm);
}

private var onSubmitForm(event:AppEvent):void
{
    childView.showButtonBackground(); // TRY TO DO THIS INSIDE THE VIEW COMPONENT INSTEAD
    sendNotification( AppConstants.SUBMIT_FORM, childView.myDataVO);
}

private function get childView():MovieClip
{
 return viewComponent as MovieClip;
}

If the only reason the Mediator is listening to the view component is to turn around and change the view component's state, then encapsulate the whole activity inside the view component and don't involve the Mediator at all. The only reason the Mediator should listen for events is so that it can translate them into the appropriate notifications, or pass or fetch data to or from a Proxy on behalf of the component.

In short, don't make the Mediator be the puppeteer of the view component. The component is responsible for its own behavior, the Mediator is responsible for routing data and messages into and out of the component.
« Last Edit: December 08, 2011, 08:50:06 by puremvc » Logged
4ucai
Jr. Member
**
Posts: 17


View Profile Email
« Reply #2 on: December 08, 2011, 06:40:16 »

Thanks for the reply cliff.

So, I should place the listener of the child view buttons in the class document/PanelView.as then it dispatches events which the Mediator is listening? I'm thinking the button should know it is clicked
before dispatching the event.
:
private function onBtn1Click(e:MouseEvent):void
{
  this.dispatchEvent( new Event( AppEvent.SUBMIT_FORM) );
}

Is it also a best practice say for the view component to have its own event constant, rather than using the its applicationfacade constants?
:
AppEvent.CONSTS_HERE
My issue really is I have this panelview.as which is a single movieclip that contains groups of related buttons and other widgets. If I directly change the view component's state then i would have long lines of code. Since i would introduce lots of functions for the interaction. Is it ok if i do this? Although, I totally get your point regarding the role of the mediator.

I initially got the impression from the best-practices

View & Mediators
The View primarily caches named references to Mediators. Mediator code stewards View Components, adding event listeners, sending and receiving notifications to and from the rest of the system on their behalf and directly manipulating their state.
« Last Edit: December 09, 2011, 03:26:16 by 4ucai » Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #3 on: December 09, 2011, 07:53:18 »

So, I should place the listener of the child view buttons in the class document/PanelView.as then it dispatches events which the Mediator is listening?
Yes. And if you are going to be listening for those events somewhere farther up the display list, then make sure set bubbling to true for the event. For instance, if the button is in a panel, which is inside a tabbed navigation component and the mediator is listening to the tabnav, then you'd need the event to bubble up.

Is it also a best practice say for the view component to have its own event constant, rather than using the its applicationfacade constants?
View components should know about nothing other than your value objects. The easiest thing to do is create a custom event called AppEvent, and it has constants for all the user intentions that will arise from the interface in the form of an event. Make it have a data property so it can carry things and the Mediator won't have get the data from the component itself. In the Mediator, you translate these events to notifications for other mediators or commands to work with. Put those constants on an AppConstants file. Don't worry that sometimes you duplicate a constant on the event and the constants file. There may be overlap (e.g. AppEvent.EDIT_ITEM, AppConstants.EDIT_ITEM), but they are never one to one, and the separation can be thought of as a protocol. One side defines user intentions, the other defines system responses.

My issue really is I have this panelview.as which is a single movieclip that contains groups of related buttons and other widgets. If I directly change the view component's state then i would have long lines of code. Since i would introduce lots of functions for the interaction. Is it ok if i do this?
Encapsulate the state management inside the component itself. Your brain is in charge of its own state. There's a lot of stuff in it and it's very complex, but it works, and the liver doesn't have to be directly involved in every thought. In the same way, you may find that your view components are sometimes quite large because they have a lot of code in them for managing their own state. You start to think, 'well, I have this mediator where I could offload a bunch of this code,' right? Wrong.

If your panel has tons of objects inside it such that managing all their states is cumbersome, then subdivide your panel into multiple components. If the panel has a graph with associated controls, and a data grid with bunch of filtering controls, then break it down. Move the graph and controls into a custom component, and move the datagrid and its filter into another. now the panel only contains two components, and its code for managing them becomes way simpler. Inside the custom graph component, you have only the code for managing the graph and in the custom grid component, you have just the filter and display of the data in the grid. The panel probably gets the data that both components work with from the mediator and passes it on to them. But they are now in charge of their own behaviors and will consume the data and present themselves accordingly.

So in short, if your View Component is getting bloated it is not a sign that your Mediator needs to take on more responsibility, instead, it is an indicator that you need to subdivide your View Component.

-=Cliff>
Logged
4ucai
Jr. Member
**
Posts: 17


View Profile Email
« Reply #4 on: December 09, 2011, 06:29:53 »

Very well said, everything is clear to me now!

Thanks cliff, your the Man!!!!
Logged
Pages: [1]
Print