0

We are using an Angular app on our Site. The Visualforce page just loads the script from a static resource and we're good to go.
Some things are still done on the VF page (and controller). Like logging the user into the Community.

<apex:actionFunction name="communityLogin" action="{!login}"></apex:actionFunction>

The angular app calls window.communityLogin with the username and password that the user input.
And that calls the Apex controller function:

public PageReference login(){
    String redirectPage = '/login-success';
    PageReference loginPage;
    if(String.isNotBlank(username) && String.isNotBlank(password)){
        loginPage = Site.login(username, password, redirectPage); 
    }
    if(loginPage != null){
        return loginPage;
    }
    else{
        //this is where I want to handle the error
        return null;
    }
}

When everything works it's great.
The problem is when the things don't work. If the user has a typo or isn't actually a user or whatever.
So we need a way to notify the user that the login failed for whatever reason and that they should try again or reset the password.

How can I get that event to the client app? if Site.login() fails it returns null. I can catch this event in the controller. But the actionFunction wants to send the user to a PageReference no matter what happens. Even if I return null it takes the user to the Community's designated index page.
At first we were redirecting the user to a page within the Angular app saying that something went wrong with the login.
But that's not nice. Why should the user have to wait for the entire Visualforce page to be reloaded? I should be able to notify them in the app without reloading the entire page.

I tried using the onbeforeunload event in the app, but it's not really designed for this.
I don't want a <apex:pageMessage> type solution, since we're not actually displaying a Visualforce page. I want to prevent the navigation event on a failed login in such a way that the Angular app can recognize it and notify the user in a friendly manner.

0

So here's the thing.
Returning null to the <apex:actionFunction> should be sufficient. What I was doing wrong was I didn't set the reRender attribute on the actionFunction. So that when the controller function returned null the actionFunction reloaded the whole page.

Given that, the solution is simple.
Add this to the VF page:

<apex:outputText id="loginFailedVar" value="{!loginFailed}"></apex:outputText>

Then just add rerender="loginFailedVar" to the apex:actionFunction.
Now that that's set up add this to the controller function:

if(loginPage != null){
    loginFailed = false;
    return loginPage;
}
else{
    loginFailed = true;
    return null;
}

And now we have something on the page that the client app can look for and notify the user if the login failed. And all without reloading the page

And if we don't want the page to display a random true or false somewhere (and who doesn't want that) we can add style="position: absolute; top: -100px;" html-aria-hidden="true" to the new outputText to hide that from users and screen readers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.