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: Accessing properties on components from Commands  (Read 9051 times)
Allen
Newbie
*
Posts: 5


View Profile Email
« on: October 13, 2008, 04:18:02 »

Hi,

Say I need to find out the value of a Slider or which item is Selected on a List from a Command. Should I add getters to the component's mediator to give it access (I know I could expose the component but that would be bad)?

Just seems like overcomplicating things - a getter for a getter...
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #1 on: October 13, 2008, 03:45:56 »

A getter for a getter is not an unheard of thing in the role of actors such as Mediator, Proxy and Facade (which are all very similar in that they all act sort of like a broker or go-between).

Here is where we want to have the component expose an API. We dont want the mediator OR the command to reach into the component to get its slider's current position. We want our component that has a slider to expose a public variable that gets its value via binding from that slider's value.

from MyComponent:
:
<mx:Script>
<![CDATA[
      public static const COOLNESS_CHANGED:String = 'coolnessChanged';
      public var coolness:Number;                   
      public var item:ItemVO;

]]>
</mx:Script>

<mx:Binding destination="coolness" source="coolnessSlider.value"/>

<mx:VSlider id="coolnessSlider" value="{coolness}"
                 minimum="0" maximum="10"
                 change="dispatchEvent(new Event(COOLNESS_CHANGED))"/>

<!-- Display the item -->
<view:MyItemDisplayComponent id="itemDisplay" item="{item}"/>


Parts of the MyComponentMediator might look like the following (note there's no need for the Mediator to know about the slider, either, leaving us free to refactor the slider to something else if we want, like a combo box):

:
private function get myComponent():MyComponent
{
    return viewComponent as MyCompoent;
}

override public function onRegister():void
{
   myComponent.addEventListener( MyComponent.COOLNESS_CHANGED, onCoolnessChanged);
}

override public function handleNotification( note:INotification ):void
{
    switch (note.getName())
    {
        case ItemProxy.ITEM_RETRIEVED:
        case ItemProxy.ITEM_UPDATED:
     myComponent.item:ItemVO = note.getBody() as ItemVO;
             myComponent.coolness=itemVO.coolness;
             break;
     }
}

private function onCoolnessChanged(event:Event):void
{
    sendNotification(ApplicationFacade.APPLY_COOLNESS, [myComponent.item, myComponent.coolness]);
}

Then inside ApplyCoolnessCommand (notice there's no need to ask the mediator or to know the slider):

:
override public function execute( note:INotification ):void
{
    var args:Array = note.getBody();
    var item:Number = args[0];
    var coolness:Number = args[1];
   
    if (coolness == item.coolness) return; // debounce
   
    var itemProxy:ItemProxy = facade.retriveProxy(ItemProxy.NAME) as ItemProxy;   
    itemProxy.updateCoolness(args); // this will result in a ItemProxy.ITEM_UPDATED note being sent...

    // do other stuff that justified doing this in a command instead of back in the Mediator

}

Hope this helps,
-=Cliff>
Logged
Allen
Newbie
*
Posts: 5


View Profile Email
« Reply #2 on: October 14, 2008, 10:04:09 »

Hi CLiff,

Thanks for replying in such depth. I get the idea of binding to the component's property and exposing it through a variable in the view that contains it, and your example works perfectly in the event the change occurs in the component and moves then to the command, but what if the change has occured on another component which has triggered a command and the command needs data from the slider? The slider's mediator still needs to allow the command some way of acessing its value.

In your example:

Component changed > Medaitor Sends CHANGED > Command Takes Action

What I am asking:

Component1 changed > Component1 Mediator sends CHANGED > Command needs value from Component2 so Component2's Mediator must expose this property via a getter

Hope that makes sense...

Logged
Jason MacDonald
Sr. Member
****
Posts: 243


View Profile Email
« Reply #3 on: October 14, 2008, 10:43:23 »

Sounds to me like it is something that should be saved in your model if it's being used in multiple places. Use Cliff's example above to set the value on the model when it changes, then later have commands request the info from the model when they need to "read" it.

I guess it depends on the level of importance the value has. The above might be overkill and probably shouldn't be done if the value is purely a view related value, you have to be the judge on that. The other option is to expose a getter on the Mediator that then gets it from the component. I don't see anything wrong with that if you only need one or two values like this. But if you need to read in multiple values and reuse them, I'd argue you are better off creating a VO and storing it in your model somewhere and updating/getting values from that.

A third option is to add listeners to the component in the mediator, and have it update a public var. Then commands read the var on the mediator but there's no direct access the component (since it got its value from the change event).

:
public var sliderValue:Number;

public function onRegister():void {
     viewComponent.addEventListener(Event.Change, onChangeHandler, false, 0, true);

}

public function onChangeHandler(event:Event):void {
     sliderValue = event.target.slider.value //probably use a custom event containing the value rather than direct access
}
« Last Edit: October 14, 2008, 10:53:36 by jasonmac » Logged
Pages: [1]
Print