简体   繁体   中英

Problem with f:ajax in JSF requiring double clicks to execute

I'm having the same issue on a few places and I'm getting fairly frustrated.

Whenever I try to trigger an ajax event it always requires two clicks, the first one simply does nothing.

I've tried firing the first click and then manually refresh the site but again, nothing happens. It always needs to be two clicks to fire the event.

The below code shows a simple loginform using composite. Here the login button requires two clicks to fire.

The main body

<body>
    <h:outputScript library="js" name="topMenuJS.js" />


    <div class="topMenu">

        <f:ajax execute="pageNavForm" render=":currentMainContent">
            <h:form id="pageNavForm">
                <h:commandLink  styleClass="selector"   rendered="#{viewErrandsBean.userID.name != null}"   action="#{renderHandler.showCreateIssue()}" value="Create errand" />
                <h:commandLink  styleClass="selector"   rendered="#{viewErrandsBean.userID.name != null}"   action="#{renderHandler.showIssue()}"       value="View errand" />
                <h:commandLink  styleClass="selector"   rendered="#{viewErrandsBean.userID.admin}"          action="#{renderHandler.showCreateUser()}"  value="Create user" />
                <h:commandLink  styleClass="lastSelector"                                                   action="#{renderHandler.showLogin()}"       value="Login" />
            </h:form>
        </f:ajax>

        <div style="clear:both;" />

    </div>

    <h:panelGroup layout="block" id="currentMainContent">

        <h:panelGroup rendered="#{renderHandler.loginPanel}" id="loginPanel"
            layout="block">

            <ui:include src="/content/login/login.xhtml">
                <ui:param name="renderID" value=":pageNavForm" />
            </ui:include>
        </h:panelGroup>
     </h:panelGroup>
</body>

And login.xhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<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:ui="http://java.sun.com/jsf/facelets">

<ui:composition>

<h:outputStylesheet library="css" name="loginPageCSS.css" />

    <h:panelGroup class="centerBox">
        <h:form>
            <table>
                <tr>
                    <td>Username</td>
                    <td><h:inputText value="#{viewErrandsBean.loginName}" /></td>
                </tr>
                <tr>
                    <td>Password</td>
                    <td><h:inputSecret value="#{viewErrandsBean.loginPass}" /></td>
                </tr>
                <tr>
                    <td>
                    <h:commandButton value="Login" action="#{viewErrandsBean.authenticateUser()}" >
                        <f:ajax execute="@form" render="#{renderID}" />
                    </h:commandButton>
                    </td>
                </tr>
            </table>
        </h:form>
    </h:panelGroup>

</ui:composition>
</html>

Thanks in advance :)

-----------EDIT-----------

I believe I've found the root of the problem, but I'm not sure how I can fix it or why it is there.

The problem with requiring a double click only presents itself after rendering a component with that "Rendered = 'boolean'" attribute. Or even more specific, only after it goes from "Rendered = false", to "Rendered = true".

The following code works as intended if rendered is set as true.

<h:panelGroup rendered="#{renderHandler.loginPanel}" id="loginPanel" layout="block">

Here's the answer you were not looking for: instead of using "rendered" to hide your login form, instead use CSS to hide it and javascript to show it. You'll get a better response time for the form than having to go back to the server just to decide to show the form. I realize this might not work for the other situations you didn't mention.

I believe you are working in a gray area (to most of us) in the interaction between JSF 2 and Facelets. When you ask the page during ajax or post-back to render a new element in the composition, you are adding to the JSF component tree rather than being part of it when it was built from scratch. That's why you see the proper behaviour when you do set rendered to true.

In combination with passing parameters between the parts of the composition, I wouldn't guarantee that renderID is set to what you think it is when you first click login.

You should be able to confirm by outputting the value of renderID using h:outputText.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM