0

我有验证问题,因为我只希望在单击屏幕上的提交按钮时进行验证,而不是在单击另一个按钮时进行。

在显示的页面中 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 中包含的丰富s0.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.
}

我的丰盈豆:

@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空或有错误的值,<p:commandButton value="Select Set" .../>则包含abundances0.xhtml的无效。它应该使用所选菜单更新显示,否则它会这样做。我将immediate 属性设置为<p:commandButton value="Select Set" />to true,但它仍然不起作用。我只希望在单击“提交”按钮时进行验证,而不是别的。

我尝试了另一种方法:validate使用模拟器 bean 中的标志来禁用验证,直到需要它为止。也就是说,当option1页面被访问时是false,禁用是true,并且在单击提交按钮之前不进行任何验证,此时它被设置为true,所以禁用是false。不幸的是,这不起作用,因为 JSF 认为页面是有效的,并在执行验证之前离开它。尽管之前在模拟器 beanvalidate()中执行过这一事实。submit()这通过在它们中的每一个中插入一个打印语句来确认。

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


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

首先,我将 immdiate="true" 放在命令按钮中,该按钮在我的 faces0.xhtml 文件中选择一个菜单:

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

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

public void selectSet0(ActionEvent e) {
    selectSet(0);
    FacesContext.getCurrentInstance().renderResponse(); 
}

但它仍然不起作用。如果我单击该按钮,除非在 option1.xhtml 文件开头的 teff1 输入字段中已经存在有效值,否则不会发生任何事情。我需要这个按钮和其他类似的按钮一起工作,无论输入字段中有什么,直到单击提交按钮。据我所知,我做的一切都是正确的。

顺便说一句,我将 JSF 2.0 与 PrimeFaces 3.4.2 和 Eclipse Indigo 一起使用。

4

2 回答 2

3

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

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

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

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

于 2013-01-24T19:54:19.413 回答
2

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

在 JSF 中,输入和命令组件有一个immediate属性,这意味着那些具有该属性true值的组件将在该APPLY_REQUEST_VALUES阶段进行处理,而不是经历整个 Faces 的生命周期。

行为因组件类型而略有不同:

  • 输入组件immediate="true"将在阶段而不是一个阶段进行验证APPLY_REQUEST_VALUESPROCESS_VALIDATION
  • 命令组件immediate="true"将在阶段而不是阶段执行APPLY_REQUEST_VALUESINVOKE_APPLICATION

因此,要跳过验证,一种可能的方法是使用<h:commandButton />with 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
}

注意:请记住,当使用即时命令提交表单时,将触发该表单的所有即时输入中的验证。

于 2013-01-24T14:38:54.807 回答