Search code examples
apache-flexeventsactionscriptflex4dispatchevent

Trouble with dispatching events from external AS class in Flex


I've been trying this for a day now and I can't work it out.

I have a main application Planner.mxml. This view has a couple of custom components, one of which is LoginView.mxml. In LoginView.mxml I do the following:

protected function btnLoginClick(event:MouseEvent):void
{
    try
    {
        var login:Login = new Login(txtEmail.text, txtPassword.text);       
    } 
    catch(error:Error) 
    {
        Alert.show(error.message, "Oops!");
    }
}

I create a new instance of my Login class and send some parameters to the constructor. My constructor looks like this:

public function Login(email:String, password:String)
        {
            if(email == "" || password == "")
            {
                throw new Error("Please complete all fields.");
            }
            else
            {
                var loginRequest:HTTPService = new HTTPService();
                var parameters:Object = new Object();

                parameters.email = email;
                parameters.password = password;

                loginRequest.url = Globals.LOGIN_URL;
                loginRequest.resultFormat = "object";
                loginRequest.method = "POST";
                loginRequest.addEventListener("result", loginHandleResult);
                loginRequest.addEventListener("fault", loginHandleFault);
                loginRequest.send(parameters);
            }
        }

Here I check if all fields are complete, and if so, I put the constructor parameters in a parameters object which I then send to the HTTPService, which is a simple PHP file that handles the request, checks with the db and returns some xml. (This might not be the best way, but this really isn't too important at this point).

If the user is logged in successfully, the xml will contain a status property which is set to true. I check for this in the result event handler of the HTTP service. This is where everything goes wrong though.

protected function loginHandleResult(event:ResultEvent):void
        {
            if(event.result.status == true)
            {
                trace("logged in");
 // here stuff goes wrong
                var e:LoggedInEvent = new LoggedInEvent("loggedIn");
                dispatchEvent(e);
            }
            else
            {
                trace("not logged in");
                Alert.show("Wrong credentials.", "Oops!");
            }
        }

As you can see, when the user is successfully logged in, I want to dispatch a custom event; if not, I show an alert box. However, this event doesn't dispatch (or at least, I don't know how to listen for it).

I would like to listen for it in my main application where I can then change my viewstate to the logged-in state. However, the event never seems to get there. I listen for it by having loggedIn="loggedInHandler(event)" on my loginComponent.

Any idea how to do this? Thanks in advance. I would really appreciate any help.


Solution

  • First, your Login needs to extend event dispatcher or implement IEventDispatcher. I'm not sure why you're getting compiler errors trying to dispatch events from it.

    Next, you need to listen to the new Login instance for that event.

    However, you have an architectural problem here that your View should NOT be handling business logic and it should DEFINITELY not be creating new objects that are not its own children on the Display List.

    Instead, you should dispatch an event from the View that REQUESTS that a login occur, and then that request should be handled further up. Depending on the scale of your application, this can be the main mxml file or separate controller or Command logic. It is ok for the View to do a minimal amount of validation prior to dispatching the Event, but ideally you would want to encapsulate this stuff into a PresentationModel (because it is easier to test).