使用JSF 2进行验证只需要提交

时间:2013-01-24 14:23:40

标签: validation jsf primefaces

我遇到验证问题,因为我只想在屏幕上点击提交按钮时进行验证,而不是在点击其他按钮时进行验证。

在显示的页面中,option1.faces是主文件option1.xhtml和几个包含的文件。下面是主页面中的代码片段和两个包含的文件:

option1.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>

option1.xhtml中包含的wtances0.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"/>

包含在option1.xhtml中的footerButtons.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.

}

MySimulatorBean:

@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.
}

option1 (xhtml和bean文件)中,用户输入teff1的值,该值必须介于teff1Minteff1Max之间,从属性文件中获取。这项工作正常,如果teff1的值未给出或超出范围,点击“提交”按钮,如footerButtons.xhtml中所示,提交失败并且<h:message/>标记显示错误。

但是,在点击“提交”之前,如果teff1的输入字段为空或值错误, 包含的<p:commandButton value="Select Set" .../>中的abundances0.xhtml不起作用。它应该用选择的菜单更新显示,否则它会。我设置immediate <p:commandButton value="Select Set" />true的属性,但仍然不起作用。我只希望在单击“提交”按钮时进行验证,而不是其他任何内容。

我尝试了另一种方法:模拟器bean中的标志validate用于禁用验证,直到需要它为止。也就是说,当option1页面被访问时,它是false,被禁用的是true,并且在点击提交按钮之前不会进行任何验证,此时它被设置为{{ 1}},禁用true。不幸的是,这种情况不起作用,因为JSF认为该页面是有效的并且在执行验证之前导航它。尽管false在模拟器bean中validate()之前执行,但这是事实。通过在每个插入中插入一个print语句来确认。

有没有人知道发生了什么?是否有一种简单的方法可以确保仅在单击提交按钮时进行验证?否则显示屏被锁定,我无法使其他按钮工作。


非常感谢您的澄清,我完全按照您的建议行事。我做了以下事情:

首先我在命令按钮中输入immdiate =“true”,选择我的abundances0.xhtml文件中的菜单:

submit()

然后我在我的丰富bean java文件中更改了操作:

<p:commandButton value="Select Set" actionListener="#{abundance.selectSet0}" update="abundances0" immediate="true"/>

但它仍然无效。如果我单击该按钮没有任何反应,除非开头的option1.xhtml文件中的teff1的输入字段中已有有效值。在点击提交按钮之前,无论输入字段中是什么,我都需要使用此按钮以及其他类似按钮。据我所见,我正在做的一切正确。

因此,我正在使用PrimeFaces 3.4.2和Eclipse Indigo的JSF 2.0。

2 个答案:

答案 0 :(得分:4)

<p:commandButton>默认处理整个表单,如process="@form"

您需要告诉它只处理自己,如process="@this"

<p:commandButton ... process="@this" />

这样,不会处理(转换/验证/更新)相同表单中的所有输入组件。

答案 1 :(得分:2)

首先,JSF中的验证是在Faces生命周期之一中执行的,更具体地说,它是在PROCESS_VALIDATIONS阶段完成的。 跳过验证 的唯一方法是指示Faces的生命周期 跳过该阶段

在JSF输入&amp;命令组件具有immediate属性,这意味着具有true值的属性将在APPLY_REQUEST_VALUES阶段处理,而不是遍历整个Faces的生命周期。

根据组件的类型,行为略有不同:

  • immediate="true"的输入组件将在APPLY_REQUEST_VALUES阶段验证而不是PROCESS_VALIDATION阶段。
  • immediate="true"的命令组件将在APPLY_REQUEST_VALUES阶段执行而不是INVOKE_APPLICATION

因此,要跳过验证,可能的方法是使用<h:commandButton /> immediate="true",然后在辅助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
}

注意 :请注意,提交带有立即命令的表单时,会触发所有立即验证输入该表格。