10

I have a custom component that includes a logout button (using a commandButton) which is used on several pages of a Force.com site. I have written a controller for this component which includes a simple action for the button which sets a cookie and then logs the user out by returning a PageReference to the login page.

However, when I click the logout button, the user is not redirected to the login page, but rather to the actual parent page of the custom component (i.e. the page that the user is already on). On inspection of the generated HTML I see that the component has a form tag which has an action set to the url of the parent page.

So when I click on the commandButton the button must be submitting this form rather than using the returned PageReference from the controller. I can see that the component controller action is running and is returning the correct url.

I wonder first of all why the form for this component is being generated with the action having it's parent page's url, and secondly if this is obligatory then how I can prevent this.

public PageReference setCookieAndLogOut() {

    Util u = new Util();
    u.setUserLoggedOutAndExpireWebsiteSession(sessionId);

    PageReference pRef = new PageReference('/apex/loginpage');
    pRef.setRedirect(true);
    return pRef;
}


<apex:component controlle="mycontroller">
    <apex:form>
        <apex:commandButton action="{!setCookieAndLogOut}" value="Log Out" />
    </apex:form>
</apex:component>

Generated HTML:

<form id="thePage:j_id6:j_id7:j_id11" name="thePage:j_id6:j_id7:j_id11" method="post" action="/homepage" enctype="application/x-www-form-urlencoded">
    <input type="submit" name="thePage:j_id6:j_id7:j_id11:j_id13" value="Log Out">
</form>

Many thanks

6

A custom component is rendered as part of the parent apex:page, and an apex:form in a custom component is rendered as part of the page. It has to submit (action='...') to the parent page - the component only exists in the context of the parent. But other parts of the page (including hidden inputs) route the action to the component's controller. If you aren't ending up on the page expected, it's probably due to an issue with setCookieAndLogOut(). You could start with a debug statement in setCookieAndLogOut to confirm to yourself that the controller method is being called.

Is 'loginpage' an apex page you've created? If so, you'll need '/apex/loginpage'. I don't believe PageReference('loginpage') will produce a link to the system login page. I can't find documentation of it, and it doesn't work for me in a dev org.

I'm not clear what your cookie logic is; if you just need a link to log the user out Salesforce, the following should work:

<apex:outputLink value="{!URLFOR('/secur/logout.jsp')}" >Logout</apex:outputLink>

Warning: this isn't documented behavior; it's relying on the system logout link being located at /secure/logout.jsp, and so could change in the future. That said, I'm not aware of a documented method of adding a logout link to a page or forcing a logout via apex code.

  • Hi Jason. Thanks for your answer. The setCookieAndLogOut(0 method was executing correctly. The issue seemed to be that I wasn't returning false from the onclick event of the command button, so I presume that this was allowing the unwanted page action to be fired off. Yes, the PageReference was 'apex/loginpage'. I just put that in for sake of example, but you're right it's not a working example, so I should change it. – Joe Oct 8 '13 at 14:44
1

The apex:form tag supports "pass through attributes" From the documentation:

To add a pass-through attribute to, for example, an component, prefix the attribute with “html-” and set the attribute value as normal.

<apex:outputPanel layout="block" html-data-role="panel" html-data-id="menu">
    <apex:insert name="menu"/>    
</apex:outputPanel>

<apex:outputPanel layout="block" html-data-role="panel" html-data-id="main">
    <apex:insert name="main"/>    
</apex:outputPanel>

This produces the following HTML output. div id="..." data-id="menu" data-role="panel"> /div>

div id="..." data-id="main" data-role="panel"> /div>

you should be able to pass through an "action" attribute that will then submit the form to the page you want.

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.