Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSF ajax listener

Tags:

ajax

jsf

jsf-2

I'm trying to figure out how to log out a user with an f:ajax call using JSF and a backing managed bean. The problem I'm having is that I can't quite figure out why the call order for the Ajax listener and the rerender of the login form.

Below is the very simplified code. The basic idea of the code is this

if (uid != null) {
    // show log out
} else {
    // show log in
}

I am clearly not understanding something about how the ajax listeners and the form rerender is done.

The JSF page

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:c="http://java.sun.com/jsp/jstl/core">
  <h:head>
    <title>Facelet Title</title>
  </h:head>
  <h:body>
    <f:view>
      <h:form id="loginForm">
        <c:choose>
          <c:when test="${userBean.uid != null}">
            <span>Hi, #{userBean.uid}</span>
            <h:commandButton value="Logout">
              <f:ajax event="click" listener="#{userBean.logout}" render="loginForm"/>
            </h:commandButton>
            </c:when>
            <c:otherwise>
            <span>User name: </span>
            <h:inputText value="#{userBean.uid}" id="uid" />
            <h:commandButton value="Login" action="#{userBean.login}" />
            </c:otherwise>
          </c:choose>
        </h:form>
      </f:view>
    </h:body>
</html>

The Bean

package test.auth;

import java.io.Serializable;
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import javax.faces.event.AjaxBehaviorEvent;

@Named(value="userBean")
@SessionScoped
public class UserBean
    implements Serializable
{
    private static final long serialVersionUID = -4292770567982457272L;

    private String uid;
    /** Creates a new instance of UserBean */
    public UserBean() {
    }

    public String getUid()
    {
        return uid;
    }

    public void setUid(String uid)
    {
        this.uid = uid;
    }

    public String login () {
        return "faces/index.xhtml";
    }

    public void logout (AjaxBehaviorEvent event) {
        this.uid = null;
    }
}

The problem with the code is that when clicking logout the form reloads but it is still in the logged in state even though the uid has been set to null. I've checked this with the debugger. So how do I make the render be executed AFTER the ajax listener?

like image 578
Matti Lyra Avatar asked Feb 18 '11 10:02

Matti Lyra


1 Answers

The JSTL tags are executed during view build time, not during view render time. At the moment JSF is reusing the view state for re-render, the JSTL tags won't be re-executed, simply because they are not there anymore.

You want to use JSF rendered attribute instead.

<h:form id="loginForm">
  <h:panelGroup rendered="#{userBean.uid != null}">
    <span>Hi, #{userBean.uid}</span>
    <h:commandButton value="Logout">
      <f:ajax event="click" listener="#{userBean.logout}" render="loginForm"/>
    </h:commandButton>
  </h:panelGroup>
  <h:panelGroup rendered="#{userBean.uid == null}">
    <span>User name: </span>
    <h:inputText value="#{userBean.uid}" id="uid" />
    <h:commandButton value="Login" action="#{userBean.login}" />
  </h:panelGroup>
</h:form>
like image 99
BalusC Avatar answered Nov 03 '22 00:11

BalusC