验证失败后重新评估所需的表达式
Re-evaluate required expression after validation failed
我有一个表单,其中包含一些必填字段,具体取决于 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 1
提交表单,并且 primefaces 仍然需要所有三个字段作为必填项。
我尝试为按钮添加一个 resetInput:
<p:resetInput target=":myForm" />
而不是 immediate="true"
到 selectOneMenu
,没有任何成功。
有什么想法吗?
Note: The PrimeFaces version is 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>
这个问题最初有点奇怪,因为它包含一些不合逻辑的行为,就像 OP 所说的那样,无法通过 [=15] 上的 p:resetInput
或 resetValues="true"
属性来解决=].
感谢@Alessandro 通过最初创建 [mcve] 并随后在聊天中响应评论。谢谢你,与其他一些看不到 [mcve] 的价值并积极回复的人相比,这是有益的。
我做的第一件事是更改代码中一些可能不相关的不合逻辑的东西
- selectedItem 的 backingbean 中的类型从
String
到 int
,因为它实际上就是这样。
- 也将字段从
String
更改为 int
,因为它们带有 p:inputNumber
- 在更改 select 时将字段设置为
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 中
- 从
process
属性中删除了 field1 field2 field3
,因为它看起来毫无用处(提交发生在 'submit',不需要 ajax 提交)。
- 也将它们从
update
属性中删除(更改后字段的更改不需要更新)
- 更改了 actionListener on the
p:commandButton
to an `action
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>
然后对我来说它开始了 'working'。在聊天中,由于特定原因,OP 在流程中具有固定字段列表并更新属性变得很明显。
- 在更新属性中,因此当 select 从例如更改为3 到 2,可以清除第三个字段(在 bean 中设置),需要一个 'upate' 使其为空。
- 在进程属性中,所以当 select 更改为例如3,将提交并更新第二个字段(不是 bean 中的 set/cleared)。如果它不在 process 属性中,则将放回 bean 的原始值,有效地覆盖用户可能输入的值。
但是这种组合是导致奇怪行为的原因,因为如果处理了某些东西,它也会被验证(在这种情况下与是否需要某些东西有关)。有三个空字段,将 select 设置为 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 放在进程或更新属性中,所有工作都按要求进行(双关语)
我有一个表单,其中包含一些必填字段,具体取决于 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 1
提交表单,并且 primefaces 仍然需要所有三个字段作为必填项。
我尝试为按钮添加一个 resetInput:
<p:resetInput target=":myForm" />
而不是 immediate="true"
到 selectOneMenu
,没有任何成功。
有什么想法吗?
Note: The PrimeFaces version is 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>
这个问题最初有点奇怪,因为它包含一些不合逻辑的行为,就像 OP 所说的那样,无法通过 [=15] 上的 p:resetInput
或 resetValues="true"
属性来解决=].
感谢@Alessandro 通过最初创建 [mcve] 并随后在聊天中响应评论。谢谢你,与其他一些看不到 [mcve] 的价值并积极回复的人相比,这是有益的。
我做的第一件事是更改代码中一些可能不相关的不合逻辑的东西
- selectedItem 的 backingbean 中的类型从
String
到int
,因为它实际上就是这样。 - 也将字段从
String
更改为int
,因为它们带有p:inputNumber
- 在更改 select 时将字段设置为
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 中
- 从
process
属性中删除了field1 field2 field3
,因为它看起来毫无用处(提交发生在 'submit',不需要 ajax 提交)。 - 也将它们从
update
属性中删除(更改后字段的更改不需要更新) - 更改了 actionListener on the
p:commandButton
to an `action
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>
然后对我来说它开始了 'working'。在聊天中,由于特定原因,OP 在流程中具有固定字段列表并更新属性变得很明显。
- 在更新属性中,因此当 select 从例如更改为3 到 2,可以清除第三个字段(在 bean 中设置),需要一个 'upate' 使其为空。
- 在进程属性中,所以当 select 更改为例如3,将提交并更新第二个字段(不是 bean 中的 set/cleared)。如果它不在 process 属性中,则将放回 bean 的原始值,有效地覆盖用户可能输入的值。
但是这种组合是导致奇怪行为的原因,因为如果处理了某些东西,它也会被验证(在这种情况下与是否需要某些东西有关)。有三个空字段,将 select 设置为 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 放在进程或更新属性中,所有工作都按要求进行(双关语)