我在验证方面遇到问题,因为我只希望在屏幕上单击提交按钮时进行验证,而不是在单击另一个按钮时进行验证。
在显示的页面选项1.faces是主文件选项1.xhtml,以及几个包含的文件。 以下是主页和两个包含的文件的代码片段:
选项 1.xhtml 中的代码:
<h:inputText size="4" maxlen="5" id="teff1" value="#{option1.teff1}">
<f:validateDoubleRange minimum="#{option1.teff1Min}" maximum="#{option1.teff1Max}"
disabled="#{simulator.validate}"/>
</h:inputText>
选项1.xhtml中包含的丰富代码0.xhtml
:<h:selectOneMenu id="abundanceSet0" value="#{abundance.abunSet0}" style="height:25px; width:180px;">
<f:selectItems value="#{abundance.abunSetMap}"/>
</h:selectOneMenu>
<p:spacer width="37" height="0"/>
<p:commandButton value="Select Set" actionListener="#{abundance.selectSet0}" update="abundances0"/>
页脚按钮中的代码.xhtml包含在选项 1.xhtml 中:
<h:message for="teff1" style="color:red"/>
<h:commandButton value="Submit" disabled="#{!login.loggedIn}" action="#{simulator.submit}" onclick="resetForm()"
actionListener="#{simulator.validate}" class="button"/>
来自相应 bean 的代码片段如下所示:MyOption1Bean:
@ManagedBean(name="option1")
@SessionScoped
public class MyOption1Bean implements Serializable {
// Lots of other private variables and objects
private String teff1;
private String teff1Min;
private String teff1Max;
// Option 1 constructor to initialze limits
public MyOption1Bean() {
ResourceBundle bundle = ResourceBundle.getBundle("com.csharp.validation");
teff1Min = bundle.getString("teff1Min");
teff1Max = bundle.getString("teff1Max");
}
public String getTeff1() {
return teff1;
}
public void setTeff1(String teff1) {
this.teff1 = teff1;
}
// Lots of getters, setters, methods, etc.
}
MyAbundanceBean:
@ManagedBean(name="abundance")
@SessionScoped
public class MyAbundanceBean implements Serializable {
// Lots of other private variables and objects
public String getAbunSet0() {
return abunSet[0];
}
public void setAbunSet0(String abunSet) {
this.abunSet[0] = abunSet;
}
public Map<String,String> getAbunSetMap() {
return abunSetMap;
}
public void selectSet0(ActionEvent e) {
selectSet(0);
}
// Lots of getters, setters, methods, etc.
}
我的模拟器豆:
@ManagedBean(name="simulator")
@SessionScoped
public class MySimulatorBean implements Serializable {
// Lots of other private variables and objects
private boolean validate;
// When validate is true disabled is false so validation takes place.
public boolean isValidate() {
return !validate;
}
// When navigating away from the home page to one of the options, reset the error
// and validate flags.
public void resetError(ActionEvent event) {
error = false;
validate = false;
}
// On clicking "Submit" this enables the validate flag.
public void validate(ActionEvent event) {
validate = true;
}
// On clicking "Submit" this gets the user's input, and if succesful sends it to an output file then
// navigate to a "Success" page, otherwise return to the original page.
public String submit() {
// Code to check for errors and output data to a file.
}
// Lots of getters, setters, methods, etc.
}
在选项 1(xhtml 和 Bean 文件)中,用户输入一个值 teff1
,该值必须介于 teff1Min
和 teff1Max
之间,这是从属性文件中获取的。 这工作正常,如果未给出teff1
的值或超出范围,则在单击"提交"按钮时,如footerButtons.xhtml
中所示,提交失败,并且<h:message/>
标签显示错误。
但是,在单击"提交"之前,如果teff1
的输入字段为空或具有错误的值,包含的abundances0.xhtml
中的<p:commandButton value="Select Set" .../>
不起作用。 它应该使用所选菜单更新显示,否则它会这样做。 我设置了immediate
属性<p:commandButton value="Select Set" />
true
,但仍然不起作用。 我只希望在单击"提交"按钮时进行验证,仅此而已。
我尝试了另一种方法:模拟器 bean 中的标志validate
用于禁用验证,直到需要它。也就是说,当访问option1
页面时,它是false
的,禁用是true
的,并且在单击提交按钮之前不进行任何验证,此时它被设置为true
,因此禁用是false
。 不幸的是,这个剂量不起作用,因为 JSF 认为页面是有效的,并在执行验证之前离开它。 尽管事实上validate()
是在模拟器 bean 中submit()
之前执行的。 通过在它们中插入一个打印语句来确认这一点。
没有人知道发生了什么?,有没有一种简单的方法可以确保仅在单击提交按钮时进行验证? 否则显示器被锁定,我无法使其他按钮工作。
非常感谢您的澄清,我完全按照您的建议做了。 我做了以下工作:
首先,我将 immdiate="true" 放在命令按钮中,该按钮在我的 abundances0.xhtml 文件中选择一个菜单:
<p:commandButton value="Select Set" actionListener="#{abundance.selectSet0}" update="abundances0" immediate="true"/>
然后我更改了我的 abundance bean java 文件中的操作:
public void selectSet0(ActionEvent e) {
selectSet(0);
FacesContext.getCurrentInstance().renderResponse();
}
但它仍然不起作用。 如果我单击该按钮,除非开头 option1.xhtml 文件中的 teff1 输入字段中已经存在有效值,否则不会发生任何情况。 我需要这个按钮与其他类似的按钮一起工作,无论输入字段中有什么,直到单击提交按钮。 据我所知,我做的一切都是正确的。
当然,我正在使用JSF 2.0和PrimeFaces 3.4.2和Eclipse Indigo。
默认情况下,<p:commandButton>
处理整个表单,如process="@form"
.
您需要告诉它仅处理自身,如process="@this"
.
<p:commandButton ... process="@this" />
这样,不会处理(转换/验证/更新)相同表单中的所有输入组件。
首先,JSF 中的验证是在 Faces 生命周期之一中执行的,更具体地说,它是在PROCESS_VALIDATIONS
阶段完成的。跳过验证的唯一方法是指示人脸的生命周期跳过该阶段。
在JSF中,输入和命令组件具有immediate
属性,这意味着具有true
值的组件将在APPLY_REQUEST_VALUES
阶段进行处理,而不是经历整个Faces的生命周期。
根据组件的类型,行为略有不同:
- 具有
immediate="true"
的输入组件将在APPLY_REQUEST_VALUES
阶段而不是PROCESS_VALIDATION
阶段进行验证。 - 具有
immediate="true"
的命令组件将在APPLY_REQUEST_VALUES
阶段执行,而不是INVOKE_APPLICATION
阶段。
因此,要跳过验证,一种可能的方法是对 immediate="true"
进行<h:commandButton />
,然后在后备 Bean 端调用 FacesContext.getCurrentInstance().renderResponse()
或 FacesContext.getCurrentInstance().requestComplete()
来告诉 Faces 跳过剩余的生命周期阶段。
因此,在您的select0
方法应该是:
public void selectSet0(ActionEvent e) {
selectSet(0);
FacesContext.getCurrentInstance().renderResponse(); // skip the remaining phases and go straight to RENDER_RESPONSE
}
注意:请记住,提交带有即时命令的表单时,将触发该表单的所有即时输入的验证。