我想请一些帮助来理解JSF在验证阶段时显示的特定行为 失败。
我正在使用:
问题描述。
我写了一个包含4个输入字段的表单:inputText和3 selectOneMenu。 inputText是必需的 而selectOneMenus不需要任何验证。附加到第一个selectOneMenu(第32行), 是一个a4j:支持标记,以便每当触发更改事件时,第二个项目列表 并正确填充第三个selectOneMenu(第44和58行)。特别是装载后 两个项目列表,该方法强制第二个和第三个selectOneMenu的值 为空。这个机制似乎工作正常,直到我提交表单而不填写输入 text:正如预期的那样,JSF验证失败但是当我更改第一个selectOneMenu的值时, 页面将继续显示在第二个和之后JSF验证失败之前指定的值 第三个selectOneMenu(注意仍然调用actionListener和第二个和的值 第三个selectOneMenu仍被强制为null。
由于我使用的是简单的PhaseListener,因此我注意到以下内容: 在JSF验证失败之前,每次我更改第一个selectOneMenu的值,JSF生命 循环始终在渲染期间为第二个和第三个selectOneMenu调用get方法 响应阶段。通过这种方式,JSF能够“看到”这些值在此期间已设置为null 调用应用程序阶段。 验证失败后,当我更改第一个值时,JSF停止调用这些getter 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 "";
}
}
答案 0 :(得分:2)
听起来您正在观察EditableValueHolder
类型的预期行为。
如果类型的验证或转换失败,表单将在提交的状态下重新呈现。这在应用请求值阶段(JSF 2规范)的文档中有所暗示:
在此阶段结束时,组件树中的所有
EditableValueHolder
组件都将使用此请求中包含的新提交值进行更新(或者,如果存储了用于重现错误输入的足够数据,则有转换错误。)
如果转换或验证失败,更新模型值阶段将不会运行(将不会在bean上调用任何setter。)如果用户刚刚提交了一个复杂的表单,他们就不会期望所有的领域都被擦除,因为一个是错的。渲染器会发出用户提交的值,而不会调用getter(请参阅isValid()
和getSubmittedValue()
)。