【问题标题】:JSF - Update model values from view before validationJSF - 在验证之前从视图中更新模型值
【发布时间】:2012-10-10 13:00:58
【问题描述】:

我有一个包含多个组件的表单,其中一些有自己的验证和/或是强制性的。然后我还有几个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" 添加到我的“全选”按钮中,它可以工作,但它不会从模型更新视图,然后用户看不到值已经改变......所以它确实没有不行。

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

我希望你能理解我的上下文。随时要求任何澄清。 提前致谢。

【问题讨论】:

    标签: java jsf lifecycle


    【解决方案1】:

    如果您使用@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

    问候。

    【讨论】:

    • hmmm... bean 是会话范围的,但我正在开发 JSF 1.2(由于某些原因,我无法迁移到 JSF 2.0 :() . 这个解决方案可以适应我的 JSF 版本吗?谢谢!
    • 嗯,这不适用于 JSF 1.x。一种选择是使用诸如 RichFaces 之类的库来添加 ajax 功能。我过去使用过它,它很容易上手。查看我的编辑。
    • 感谢您的回答。这绝对是我的错,我没有具体说明我使用的是什么技术。是的,我也使用 RichFaces 并使用 a4j:support,但我无法正确解决问题。谢谢你的相关话题,我会研究它。
    • @jmrodrigg 没问题。部分更新页面中的组件是真正的 ajax 领域。看看我的编辑,祝你好运。问候。
    • @jmrodrigg 很高兴它成功了。你看到我的a4j:commandButtonedit了吗?
    【解决方案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>
    

    【讨论】:

    • 感谢您采用这种不同的方法。我不知道这是可能的。尽管a4j:commandButton 更适合我的目的,但很高兴知道不同的解决方案。谢谢!
    • @BalusC THX 很多次!我花了几个小时寻找这样的解决方案!
    【解决方案3】:

    在考虑了 Bento 的建议后,我意识到让它按我想要的方式工作的唯一方法是使用 AJAX a4j

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

    1. h:commandButton“全选”按钮替换为a4j:commandButton
    2. 为我的h:selectOneMenu 组件定义id 标签,这样我就可以通过之前定义的a4j:commandButton重新渲染组件。

    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>
    (...)
    

    非常感谢便当的建议!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多