JSF - 在验证之前从视图更新模型值

时间:2012-10-10 13:00:59

标签: java jsf lifecycle

我有一个包含多个组件的表单,其中一些组件有自己的验证和/或是必需的。然后我还有几个selectOneMenu个组件在其列表中具有相同的三个selectItem元素。我已经定义了三个commandButton,以便为所有列表选择相同的值(每个可能值一个commandButton)。

JSF部分

<table>
    <tr>
        <td>
            <h:outputText value="ID:" />
        </td>
        <td>
            <h:inputText value="#{MyClass.id}" id="inTxt_id" required="true">
                <f:validator validatorId="CheckIDPattern" />
            </h:inpuText>
            <h:message for="inTxt_id" errorClass="error" />
        </td>
    </tr>
</table>
<table>
    <tr>
        <td>
            <h:commandButton value="Select all opt1" action="#{MyClass.selectOpt1}" />
            <h:commandButton value="Select all opt2" action="#{MyClass.selectOpt2}" />
            <h:commandButton value="Select all opt3" action="#{MyClass.selectOpt3}" />
        </td>
    </tr>
    <tr>
        <td>
            <h:outputText value="List 1:" />
        </td>
        <td>
            <h:selectOneMenu value="#{MyClass.list1Val}">
                <f:selectItems value="#{MyClass.listOfOptions}" />
            </h:selectOneMenu>
        </td>
    <tr>
        <td>
            <h:outputText value="List 2:" />
        </td>
        <td>
            <h:selectOneMenu value="#{MyClass.list2Val}">
                <f:selectItems value="#{MyClass.listOfOptions}" />
            </h:selectOneMenu>
        </td>
    </tr>
    <tr>
         //Many other selectOneMenu components...
    </tr>
</table>
<h:commandButton action="#{MyClass.saveLists}" value="Submit" />

MyClass.java

public String selectOpt1(){
    this.list1Val = 1;
    this.list2Val = 1;
    //...
    return "";
}

//The same idea for selectOpt2 and selectOpt3.

在这种情况下,如果我的用户按下我的“全选”按钮之一而没有填写ID inputText,它会收到错误消息,但我不想要它,因为我认为他们还没有完成填写表格。我只想在用户按下“保存列表”按钮时执行验证。

我已经尝试将immediate="true"添加到我的“全选”按钮,它可以工作,但它不会从模型更新视图,然后用户看不到值已更改...所以它真的不行。

我想要实现什么?我只想在最后一个按钮(提交)时执行验证。因此,我的用户可以使用这些“全选”按钮,而无需先填写必备组件。

我希望你理解我的背景。随意要求任何澄清。 提前谢谢。

3 个答案:

答案 0 :(得分:2)

如果您使用的是@ViewScoped bean,则可以进行以下更改:

首先将您的selectOpt1方法更改为void

public void selectOpt1() 
{
    this.list1Val = 1;
    this.list2Val = 1;
    //...
}

在选择项目时,为要更新的组件提供id。我假设在这种情况下列表1:

<h:selectOneMenu id="list1" value="#{MyClass.list1Val}">
    //...
</h:selectOneMenu>

在按钮中添加f:ajax标记,该标记仅部分提交该组件进行处理:

<h:commandButton value="Select all opt1" action="#{MyClass.selectOpt1}">
    <f:ajax execute="@this" render="list1" />
</h:commandButton>

如果您计划更新多个组件,则可以按空格分隔其ID:

<f:ajax execute="@this" render="list1 list2" />

我希望它有所帮助。

修改

对不起,我没注意到你在使用JSF 1.x.在这种情况下它不起作用。

您可以使用RichFaces等库来添加ajax功能。请查看以下主题:

<强> RichFaces的

正如您所说,您使用的是RichFaces,您可以将f:ajax代码切换为a4j:support

<h:commandButton value="Select all opt1" action="#{MyClass.selectOpt1}">
    <a4j:support event="onclick" reRender=":list1" ajaxSingle="true" />
</h:commandButton>

或者使用a4j:commandButton

这样
<a4j:commandButton value="Select all opt1" reRender=":list1" ajaxSingle="true" />

有关此行为的详情,请参阅this

问候。

答案 1 :(得分:2)

required属性取决于按下的按钮。

<h:form id="form">
    <c:set var="saveButtonPressed" value="#{not empty param['form:save']}" />
    ...
    <h:inputText ... required="#{saveButtonPressed}" />
    ...
    <h:commandButton id="save" ... />
</h:form>

答案 2 :(得分:0)

在考虑了 Bento 的建议后,我想到了使其正常工作的唯一方法是使用AJAX a4j

我必须在代码中引入的更改是:

  1. 替换h:commandButton“选择所有”按钮a4j:commandButton
  2. 为我的id组件定义h:selectOneMenu标签,因此我可以通过之前定义的a4j:commandButton reRender 组件。
  3. JSF 原始页面已修改如下:

    (...)
    <table>
        <tr>
            <td>
                <a4j:commandButton value="Select all opt1" action="#{MyClass.selectOpt1}"
                    reRender="list1,list2,(...)" ajaxSingle="true" />
                <a4j:commandButton value="Select all opt2" action="#{MyClass.selectOpt2}"
                    reRender="list1,list2,(...)" ajaxSingle="true" />
                <a4j:commandButton value="Select all opt3" action="#{MyClass.selectOpt3}"
                    reRender="list1,list2,(...)" ajaxSingle="true" />
            </td>
        </tr>
        <tr>
            <td>
                <h:outputText value="List 1:" />
            </td>
            <td>
                <h:selectOneMenu value="#{MyClass.list1Val}" id="list1">
                    <f:selectItems value="#{MyClass.listOfOptions}" />
                </h:selectOneMenu>
            </td>
        </tr>
        <tr>
            <td>
                <h:outputText value="List 2:" />
            </td>
            <td>
                <h:selectOneMenu value="#{MyClass.list2Val}" id="list2">
                    <f:selectItems value="#{MyClass.listOfOptions}" />
                </h:selectOneMenu>
            </td>
        </tr>
    (...)
    

    非常感谢 Bento 为您提供建议!