如何解决验证阶段失败后,Java Server Faces会继续显示旧值忽略actionListeners设置
|| 我想请一些帮助理解JSF在验证阶段显示的特定行为 失败。 我在用着: 的Tomcat 7.0.2 JSF 1.2_12 RichFaces 3.3.3 问题描述。 我编写了一个包含4个输入字段的表单:一个inputText和3个selectOneMenu。 inputText是必需的 而selectOneMenus不需要任何验证。附加到第一个selectOneMenu(第32行), 是a4j:support标记,以便每当触发change事件时,第二个项目的列表 并且第三个selectOneMenu(第44和58行)已正确填充。特别是加载后 这两个项目列表,该方法强制第二个和第三个selectOneMenu的值 为空。在我提交表单而不填写输入内容之前,此机制似乎正常工作 文字:正如预期的那样,JSF验证失败,但是当我更改第一个selectOneMenu的值时, 该页面继续显示在第二次JSF验证失败之前指定的值,并且 第三个selectOneMenu(请注意,仍会调用actionListener,第二个和 第三个selectOneMenu仍被强制为null)。 由于我使用的是简单的PhaseListener,因此我注意到了以下几点: 在JSF验证失败之前,每次更改第一个selectOneMenu的值时,JSF的寿命 循环始终在渲染过程中为第二个和第三个selectOneMenu调用get方法。 响应阶段。这样,JSF能够“看到”那些值在执行期间已设置为null。 调用应用程序阶段。 验证失败后,当我更改第一个的值时,JSF停止调用这些获取器 selectOneMenu。 这是我的看法<?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:f=\"http://java.sun.com/jsf/core\"
xmlns:h=\"http://java.sun.com/jsf/html\"
xmlns:a4j=\"http://richfaces.org/a4j\"
xmlns:rich=\"http://richfaces.org/rich\">
<head>
<title>Prove Rich</title>
</head>
<body>
<h2>Prove Rich</h2>
<f:view>
<a4j:outputPanel ajaxRendered=\"true\">
<h:messages style=\"color:red\" />
</a4j:outputPanel>
<h:form>
<p>
Input required: <h:inputText value=\"#{provaProbReplyBean.inputrequired}\" required=\"true\" />
</p>
<p>
<h:outputText value=\"Scegli il canale:\" />
<h:selectOneMenu value=\"#{provaProbReplyBean.canale}\">
<f:selectItem itemLabel=\"--\" itemValue=\"\" />
<f:selectItem itemLabel=\"Profamily\" itemValue=\"Profamily\" />
<f:selectItem itemLabel=\"Captive\" itemValue=\"Captive\" />
<a4j:support event=\"onchange\" action=\"#{provaProbReplyBean.caricaProcBanche}\" ajaxSingle=\"true\" reRender=\"procedure,banche\" />
</h:selectOneMenu>
</p>
<p>
<h:outputText value=\"Scegli la procedura:\" />
<h:selectOneMenu id=\"procedure\" value=\"#{provaProbReplyBean.procedura}\">
<f:selectItem itemLabel=\"--\" itemValue=\"\" />
<f:selectItems value=\"#{provaProbReplyBean.procedureList}\" />
<!-- immediately save the current value -->
<a4j:support event=\"onchange\" ajaxSingle=\"true\" />
</h:selectOneMenu>
</p>
<p>
<h:outputText value=\"Scegli la banca:\" />
<h:selectOneMenu id=\"banche\" value=\"#{provaProbReplyBean.banca}\">
<f:selectItem itemLabel=\"--\" itemValue=\"\" />
<f:selectItems value=\"#{provaProbReplyBean.bancheList}\" />
<!-- immediately save the current value -->
<a4j:support event=\"onchange\" ajaxSingle=\"true\" />
</h:selectOneMenu>
</p>
<p><h:commandButton value=\"Submit\" /></p>
</h:form>
</f:view>
</body>
</html>
这是我的模型:
public class ProvaProbReply {
private String inputrequired;
private String canale;
private String procedura;
private String banca;
private Map<String,List<SelectItem>> canaliProc = new HashMap<String,List<SelectItem>>();
private Map<String,List<SelectItem>> canaliBanche = new HashMap<String,List<SelectItem>>();
private List<SelectItem> procedureList = new ArrayList<SelectItem>();
private List<SelectItem> bancheList = new ArrayList<SelectItem>();
public ProvaProbReply() {
List<SelectItem> l = new ArrayList<SelectItem>();
l.add(new SelectItem(\"Cessione del quinto\"));
l.add(new SelectItem(\"Credito al consumo\"));
l.add(new SelectItem(\"Mutui\"));
canaliProc.put(\"Profamily\",l);
l = new ArrayList<SelectItem>();
l.add(new SelectItem(\"Credito al consumo\"));
canaliProc.put(\"Captive\",l);
l = new ArrayList<SelectItem>();
canaliBanche.put(\"Profamily\",l);
l = new ArrayList<SelectItem>();
l.add(new SelectItem(\"BDL\"));
l.add(new SelectItem(\"BM\"));
l.add(new SelectItem(\"BPM\"));
l.add(new SelectItem(\"CRA\"));
canaliBanche.put(\"Captive\",l);
}
public String getInputrequired() {
return inputrequired;
}
public void setInputrequired(String ir) {
inputrequired = ir;
}
public String getCanale() {
return canale;
}
public void setCanale(String c) {
canale = c;
}
public String getProcedura() {
System.out.println(\"\\ngetProcedura called\\n\");
return procedura;
}
public void setProcedura(String p) {
procedura = p;
}
public String getBanca() {
System.out.println(\"\\ngetBanca called\\n\");
return banca;
}
public void setBanca(String b) {
banca = b;
}
public List<SelectItem> getProcedureList() {
return procedureList;
}
public List<SelectItem> getBancheList() {
return bancheList;
}
public String caricaProcBanche() {
System.out.println(\"\\nListener called\\n\");
procedureList.clear();
bancheList.clear();
if(canale != null && !canale.equals(\"\")) {
procedureList.addAll(canaliProc.get(canale));
bancheList.addAll(canaliBanche.get(canale));
}
System.out.println(\"BEFORE setting:\\n\");
System.out.println(\"\\nProcedura: \"+procedura+\"\\n\");
System.out.println(\"Banca: \"+banca+\"\\n\");
procedura = null;
banca = null;
System.out.println(\"\\n\\n\\nAFTER setting:\\n\");
System.out.println(\"\\nProcedura: \"+procedura+\"\\n\");
System.out.println(\"Banca: \"+banca+\"\\n\");
return \"\";
}
}
解决方法
听起来您正在观察
EditableValueHolder
类型的预期行为。
如果验证或类型转换失败,则将以提交状态重新提交表单。文档中的“申请请求值”阶段(JSF 2规范)对此进行了暗示:
在此阶段结束时,组件树中的所有“ 2”个组件都将使用此请求中包含的新提交值进行更新(或者,如果存在转换错误,则将存储足够的数据以重现错误的输入)。
如果转换或验证失败,那么将不会运行“更新模型值”阶段(不会在Bean上调用任何setter。)如果用户只是提交了复杂的表单,则他们不希望擦除所有字段,因为一个是错的。渲染器发出用户提交的值,并且不调用getter(请参见isValid()
和getSubmittedValue()
)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。