0
votes

I got a question about event dispatching and dispatching in flex.

My goal is to pass an email address captured in one component (Comp1) and be passed to another (Comp2). These two components are navigator content of a viewstack. The custom event dispatched the email correctly from Comp1 but somehow could not reach Comp2. The application (Main) looks like :

<fx:Script>
    <![CDATA[
        import events.LoginEventComplete;

        protected function loginHandler(event:LoginEventComplete):void
        {
            myViewStack.selectedChild = idViewMain;
        }
    ]]>
</fx:Script>

<s:Panel width="100%" height="100%">
    <mx:ViewStack id="myViewStack" selectedIndex="0" width="100%" height="100%">
        <views:Comp1 id="idViewLogin" login="loginHandler(event)"/>
        <views:Comp2 id="idViewMain"/>
    </mx:ViewStack>
</s:Panel>

The Comp1 looks like

<fx:Metadata>
    [Event(name="login", type="events.LoginEventComplete")]
</fx:Metadata>
<fx:Script>
    <![CDATA[
        import events.LoginEventComplete;

        protected function bnLogIn_clickHandler(event:MouseEvent):void{
            var e:LoginEventComplete = new LoginEventComplete("login");
            e.workemail = tiWorkEmail.text;
            dispatchEvent(e);
        }
    ]]>
</fx:Script>

<fx:Declarations>
    <!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>

<s:layout>
    <s:VerticalLayout verticalAlign="middle" horizontalAlign="center"/>
</s:layout>

<s:Panel width="400" height="500">
    <s:Label text="Email" x="130" y="150"/>
    <s:TextInput id="tiWorkEmail" top="140" left="180" right="60"/>
    <s:Button 
        id="bnLogIn"
        label="Log In"
        top="220" left="180"
        click="bnLogIn_clickHandler(event)"/>
</s:Panel> 

The Comp2 looks like

<fx:Script>
    <![CDATA[
        import events.LoginEventComplete;

        import valueObjects.Employee;

        protected function init():void
        {
            this.addEventListener(LoginEventComplete.LOGIN, mainHandler);
        }

        private function mainHandler(event:LoginEventComplete):void{
            tiWorkEmail.text = event.workemail;
        }

    ]]>
</fx:Script>

<fx:Declarations>

</fx:Declarations>

<s:layout>
    <s:VerticalLayout verticalAlign="middle" horizontalAlign="center"/>
</s:layout>

<s:Label id="idWorkEmail" text="Email"/>
<s:TextInput id="tiWorkEmail"/>

The custom event LoginEventComplete look like

package events { import flash.events.Event; public class LoginEventComplete extends Event { public var workemail:String;

public static const LOGIN:String = "login";

public function LoginEventComplete(type:String)
{
  super(type, true, false);
  this.workemail = workemail; 
}

override public function clone():Event
{
  var newEvent:LoginEventComplete = new LoginEventComplete(type);
  newEvent.workemail = workemail;
  return newEvent;
}

} }

Can someone help please? Many thanks!

Best David W

2

2 Answers

1
votes

You're realizing one of the problems that any hierarchical view structure has to pass information. This problem can be solved in severals ways, but I feel that I should tell you that you might need to look into an application framework if your application is going to get large. One like Parsley or RobotLegs.

Now, onto a solution. You won't be able to use bubbling to go from one sibling component to another, since bubbling goes up the display list (child to parent and so on). You can either listen for the event on the common parent and then push the information into the other sibling, but that's adding a lot of logic on the parent container.

An easy fix would be to create a model (a class that just has public properties to store information) that is bindable on the parent and binded into both siblings. Then if one changes the information, the other can receive that same information (or use bindings).

For example:

<fx:Script>
    <![CDATA[
        import events.LoginEventComplete;

        [Bindable] private var someData:SomeModel = new SomeModel();

        protected function loginHandler(event:LoginEventComplete):void
        {
            myViewStack.selectedChild = idViewMain;
        }
    ]]>
</fx:Script>

<s:Panel width="100%" height="100%">
    <mx:ViewStack id="myViewStack" selectedIndex="0" width="100%" height="100%">
        <views:Comp1 id="idViewLogin" login="loginHandler(event)" data="{someData}/>
        <views:Comp2 id="idViewMain" data="{someData}/>
    </mx:ViewStack>
</s:Panel>
1
votes

I can tell you that dispatched events only move up the hierarchy chain. It sounds like, based on your first code segment, you are trying to get it to move sideways.

<mx:ViewStack id="myViewStack" selectedIndex="0" width="100%" height="100%">
    <views:Comp1 id="idViewLogin" login="loginHandler(event)"/>
    <views:Comp2 id="idViewMain"/>
</mx:ViewStack>

So, one solution is to have a listener in the main component for the event which then executes a public method in the comp2. It is probably the easiest route.

Another solution may be to store the value in a global object; which both components have references to.