首页 > 解决方案 > 验证失败后重新评估所需的表达式

问题描述

我有一个表单,其中包含一些必填字段,具体取决于 a selectOneMenu,如下所示:

<p:selectOneMenu id="myList" value="#{myBean.selectedItem}">
    <p:selectItems value="#{myBean.myItems}" />
    <p:ajax listener="#{myBean.myList_change}"
            process="myList field1 field2 field3"
            update="field1 field2 field3" />
</p:selectOneMenu>

<p:inputNumber id="field1" required="true" />
<p:inputNumber id="field2" required="#{myBean.selectedItem gt 1}" />
<p:inputNumber id="field3" required="#{myBean.selectedItem gt 2}" />

我第一次按下提交按钮时,没有填写必填字段:

<p:commandButton id="mySubmit" action="#{myBean.myAction}" />

我收到验证错误,然后如果我更改selectOneMenu值,将不再评估所需的表达式。

例如,如果我提交表单时selectedItem equals to 3遇到了所有验证错误,那么我提交表单时使用selectedItem equals to 1Primefaces 仍然要求所有三个字段为必填项。

我试图向按钮添加一个resetInput:

<p:resetInput target=":myForm" />

而不是immediate="true"到的selectOneMenu,没有任何成功。

请问有什么想法吗?

注意:PrimeFaces 版本为 6.2

PS:在图片中,只有第一个字段是必需的,但应该需要所有元素。

例子

遵循完整的最小可重现示例:

xhtml 文件 (test.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://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">
<h:head>
    <title>Example</title>
</h:head>
<h:body bgcolor="white">
    <h:form>
        <p:messages showDetail="true" />
        <p:selectOneMenu id="myList" value="#{myBean.selectedItem}">
            <f:selectItem itemLabel="1" itemValue="1" />
            <f:selectItem itemLabel="2" itemValue="2" />
            <f:selectItem itemLabel="3" itemValue="3" />
            <p:ajax listener="#{myBean.myList_change}"
                process="myList field1 field2 field3" update="field1 field2 field3" />
        </p:selectOneMenu>

        <p:inputNumber id="field1" required="true" decimalPlaces="0"
            value="#{myBean.field1}" />
        <p:inputNumber id="field2" required="#{myBean.selectedItem gt 1}"
            decimalPlaces="0" value="#{myBean.field2}" />
        <p:inputNumber id="field3" required="#{myBean.selectedItem gt 2}"
            decimalPlaces="0" value="#{myBean.field3}" />

        <p:commandButton actionListener="#{myBean.submit}" update="@form" />
    </h:form>
</h:body>
</html>

豆(MyBean.java):

    package com.mkyong.common;

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean(name = "myBean")
@SessionScoped
public class MyBean implements Serializable {

    private static final long serialVersionUID = 1L;
    private static final String STRING_EMPTY = "";

    private Long selectedItem;

    private String field1, field2, field3;

    public Long getSelectedItem() {
        return selectedItem;
    }

    public void setSelectedItem(final Long selectedItem) {
        this.selectedItem = selectedItem;
    }

    public String getField1() {
        return field1;
    }

    public void setField1(final String field1) {
        this.field1 = field1;
    }

    public String getField2() {
        return field2;
    }

    public void setField2(final String field2) {
        this.field2 = field2;
    }

    public String getField3() {
        return field3;
    }

    public void setField3(final String field3) {
        this.field3 = field3;
    }

    public void myList_change() {
        final long value = selectedItem.longValue();
        if (value < 1) {
            setField1(STRING_EMPTY);
        }
        if (value < 2) {
            setField2(STRING_EMPTY);
        }
        if (value < 3) {
            setField3(STRING_EMPTY);
        }
    }

    public void submit() {
    }

}

在 web.xml 中,您应该设置欢迎页面:

<welcome-file-list>
    <welcome-file>faces/test.xhtml</welcome-file>
</welcome-file-list>

标签: primefaces

解决方案


这个问题最初有点奇怪,很奇怪,因为它包含一些不合逻辑的行为,就像 OP 所说的那样,p:resetInput不能resetValues="true"p:ajax.

感谢@Alessandro 通过最初创建 [mcve] 并随后在聊天中对评论做出响应。感谢这一点,与其他一些看不到 [mcve] 价值并积极回复的人相比,这是值得的。

我做的第一件事是更改代码中可能不相关的一些不合逻辑的东西

  • StringselectedItem 从 a到 an的 backingbean 类型,int因为它实际上就是这样。
  • 也将字段从更改Stringint's,因为它们带有p:inputNumber
  • 在选择更改时将字段设置为null而不是空字符串。

Java代码:

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean(name = "myBean")
@SessionScoped
public class MyBean implements Serializable {

    private static final long serialVersionUID = 1L;

    private int selectedItem;

    private Integer field1, field2, field3;

    public int getSelectedItem() {
        return selectedItem;
    }

    public void setSelectedItem(final int selectedItem) {
        this.selectedItem = selectedItem;
    }

    public Integer getField1() {
        return field1;
    }

    public void setField1(final Integer field1) {
        this.field1 = field1;
    }

    public Integer getField2() {
        return field2;
    }

    public void setField2(final Integer field2) {
        this.field2 = field2;
    }

    public Integer getField3() {
        return field3;
    }

    public void setField3(final Integer field3) {
        this.field3 = field3;
    }

    public void myList_change() {

        if (selectedItem < 1) {
            setField1(null);
        }
        if (selectedItem < 2) {
            setField2(null);
        }
        if (selectedItem < 3) {
            setField3(null);
        }
    }

    public void submit() {
    }
}

在 xhtml 我

  • field1 field2 field3从属性中删除了,process因为看起来没用(提交发生在“提交”上,不需要 ajax 提交)。
  • 还从update属性中删除了它们(更改后成为必需的字段更改不需要更新)
  • 将上的 actionListener更改为`actionp:commandButton

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://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">
<h:head>
    <title>Example</title>
</h:head>
<h:body bgcolor="white">
    <h:form id="myForm">
        <p:messages showDetail="true" />
        <p:selectOneMenu id="myList" value="#{myBean.selectedItem}">
            <f:selectItem itemLabel="1" itemValue="1" />
            <f:selectItem itemLabel="2" itemValue="2" />
            <f:selectItem itemLabel="3" itemValue="3" />
            <p:ajax listener="#{myBean.myList_change}"
                process="myList"/>
        </p:selectOneMenu> <br/> 

        <p:inputNumber id="field1" value="#{myBean.field1}" required="true" decimalPlaces="0" />
        <p:inputNumber id="field2" value="#{myBean.field2}" required="#{myBean.selectedItem gt 1}" decimalPlaces="0" />
        <p:inputNumber id="field3" value="#{myBean.field3}" required="#{myBean.selectedItem gt 2}" decimalPlaces="0" />

        <p:commandButton value="submit" action="#{myBean.submit}" update="@form"/>

    </h:form>
</h:body>
</html>

然后对我来说它开始“工作”。在聊天中,很明显 OP 在进程中有固定的字段列表并出于特定原因更新属性。

  • In the update attribute so when the select was changed from eg 3 to 2, the 3rd field could be cleared (set in the bean), requiring an 'upate' to make it empty.
  • In the process attribute so when the select was changed to eg 3, the 2nd field (not set/cleared in the bean) would be submitted AND updated. 如果它不在 process 属性中,则 bean 的原始值将被放回,从而有效地覆盖用户可能输入的值。

但是这种组合是奇怪行为的原因,因为如果处理了某些东西,它也会被验证(在这种情况下与是否需要某些东西有关)。拥有三个空字段,将选择设置为 3 并提交所有三个字段将失败,因为 2 是空的,但“3”也不会放入模型中。我会怀疑resetValues这里也有帮助,但它没有(也不适合我)。但是 OP 实际上想要的是有条件地更新输入字段。这个条件已经在 bean 中,您可以简单地添加更改那里的特定字段的更新

public void myList_change() {

    if (selectedItem < 1) {
        setField1(null);
    }
    if (selectedItem < 2) {
        setField2(null);
        PrimeFaces.current().ajax().update("myForm:field2");
    }
    if (selectedItem < 3) {
        setField3(null);
        PrimeFaces.current().ajax().update("myForm:field3");
    }
}

字段 1、2 和 3 完全不需要在 process 或 update 属性中,并且所有工作都按要求工作(双关语)


推荐阅读