第一次点击 commandButton 不会重定向到另一个页面

First click on commandButton doesn't redirect to another page

  1. 当我向 inputText 输入有效值(仅限数字)并单击 commandButton 时,我将被重定向到response.xhtml.

  2. 当我输入无效值时,点击页面背景,然后触发更改事件,显示消息。 现在,当我输入有效值并单击 commandButton 时, 消息隐藏,但我没有被重定向 。 当我第二次点击时,我被重定向了。

index.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!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://xmlns.jcp.org/jsf/html"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <h:form>
            <h:panelGrid>
                <h:inputText id="value" value="#{bean.value}">
                    <f:validateRegex pattern="\d+"/>
                    <f:ajax event="change" execute="@this" render="@this valueMessage"/>
                </h:inputText>
                <h:message id="valueMessage" for="value"/>
            </h:panelGrid>

            <h:commandButton value="OK" action="response"/>
        </h:form>
    </h:body>
</html>

response.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!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://xmlns.jcp.org/jsf/html">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        Value is <h:outputText value="#{bean.value}"/>
    </h:body>
</html>

Bean.java

package app;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean
@RequestScoped
public class Bean {

    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

您可能需要在 index.xhtml

中这样做
<h:form>
    <h:panelGrid>
       <h:inputText  id="value" value="#{bean.value}">
           <f:validateRegex pattern="\d+" />
       </h:inputText>
       <h:message id="valueMessage" for="value"/>
    </h:panelGrid>
    <h:commandButton value="OK"  action="response" >
          <f:ajax  execute="value" render="value valueMessage"/>
    </h:commandButton>
</h:form>

顺便说一句,在您的代码中,第一次点击是针对 change 事件,而不是针对按钮,因此如果您尝试点击页面中除按钮以外的任何位置,验证将消失并且按钮将重定向你从第一击。

您的具体问题是由隐藏消息引起的,这反过来导致命令按钮在其自身的单击事件完成之前向上移动,因此当鼠标按钮被释放并即将按下时不再位于鼠标指针下方触发表单提交。如果像这样将消息组件移动到命令按钮组件下方,

<h:commandButton value="OK" action="response"/>
<h:message id="valueMessage" for="value"/>

...那么命令按钮会在消息隐藏时停留在UI中的同一个位置,从而成功接收到它的点击事件并触发表单提交。

这只是一个UI设计问题,不是技术问题。您需要尝试确保按钮在其点击事件完成之前不会离开。

一种方法是将表单设为 2 列宽,以便消息显示在输入字段旁边而不是下方,因此不会占用更多的水平空间 space:

<h:panelGrid columns="2">

另一种方法是使用 <f:ajax delay> 属性延迟 ajax 请求(仅自 JSF 2.2 起可用)。我测试了几个值,100~200ms 似乎可以接受平均点击的时间跨度(从按下鼠标按钮到实际释放鼠标按钮的时间)。这样 ajax 请求实际上不会在单击提交按钮时触发,从而避免了按钮的移动(和 "unnecessary" 验证)。

<f:ajax render="@this valueMessage" delay="150" />

(请注意,event="change"execute="@this" 已经是默认值,为清楚起见,在上面的示例中已将它们省略;从技术上讲,render="@this" 也很奇怪,但我只是保留了它,以防你真的想在一些转换步骤后重新显示更改后的值)