Jsf 2 对actionListener中支持对象的更改未反映在绑定的UI元素中

Jsf 2 对actionListener中支持对象的更改未反映在绑定的UI元素中,jsf-2,Jsf 2,我有一个JSF页面,它有一个包含数字权重的可变数字inputText元素。这些都绑定到我的支持bean中的权重对象。我想创建一个actionListener按钮,它将在所有输入文本中重新分配权重 我可以调用backingbean中的方法,该方法将权重对象中包含的值分布在backingbean中,但由于某些原因,这些更新的值不会反映在InputText元素中 我的假设是,在更新值之前,这些值会被放回UI元素中。这表明我对JSF生命周期缺乏了解 有人能告诉我怎样才能做到这一点吗 下面是xhtml文件

我有一个JSF页面,它有一个包含数字权重的可变数字inputText元素。这些都绑定到我的支持bean中的权重对象。我想创建一个actionListener按钮,它将在所有输入文本中重新分配权重

我可以调用backingbean中的方法,该方法将权重对象中包含的值分布在backingbean中,但由于某些原因,这些更新的值不会反映在InputText元素中

我的假设是,在更新值之前,这些值会被放回UI元素中。这表明我对JSF生命周期缺乏了解

有人能告诉我怎样才能做到这一点吗

下面是xhtml文件的相关部分。对于每个子对象,我引用子对象的“newWeight”对象键。newWeight对象是在绑定到preRenderView事件的loadFamily方法中创建的:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:h="http://java.sun.com/jsf/html">

<ui:composition template="/templates/layout.xhtml">
<f:metadata>
    <f:viewParam name="familyId" required="true"
        requiredMessage="familyId is required"
        value="#{weighFamilyBacking.familyId}"></f:viewParam>
    <f:event type="preRenderView"
        listener="#{weighFamilyBacking.loadFamily}" />
</f:metadata>
<ui:define name="title">Weigh Family</ui:define>
<ui:define name="content">
    <h:form>
        <h2>Previous Weights</h2>

        <rich:dataTable value="#{weighFamilyBacking.allWeights}" var="weight"
            id="table">
            <rich:column>
                <f:facet name="header">
                    <h:outputText value="Child" />
                </f:facet>
                <h:outputText
                    value="#{weight.child.firstName} #{weight.child.lastName}" />
            </rich:column>

            <rich:column>
                <f:facet name="header">
                    <h:outputText value="Weight" />
                </f:facet>
                <h:outputText value="#{weight.weight}" />
            </rich:column>


            <rich:column>
                <f:facet name="header">
                    <h:outputText value="Weigh Time" />
                </f:facet>
                <h:outputText value="#{weight.weighTime}" />
            </rich:column>

            <rich:column>
                <f:facet name="header">
                    <h:outputText value="Payout Time" />
                </f:facet>
                <h:outputText value="#{weight.payoutTime}" />
            </rich:column>
            <rich:column>
                <f:facet name="header">
                    <h:outputText value="Payout Status" />
                </f:facet>
                <h:outputText value="#{weight.status}" />
            </rich:column>
        </rich:dataTable>

        <h2>New Weights</h2>


        <h:panelGroup id="newWeights">
            <ul>
                <ui:repeat var="child" value="#{weighFamilyBacking.children}">
                    <li><h:panelGroup layout="block">
                            <h:outputText value="#{child.firstName}" />
                            <h:outputLabel value="Lbs" for="lbs">
                                <h:inputText size="3" id="lbs"
                                    value="#{weighFamilyBacking.newWeights[child].lbs}" />
                            </h:outputLabel>

                            <h:outputLabel value="Oz" for="oz">
                                <h:inputText id="oz" size="3"
                                    value="#{weighFamilyBacking.newWeights[child].oz}" />
                            </h:outputLabel>
                        </h:panelGroup></li>
                </ui:repeat>
                <h:outputLabel value="Donate Only" for="donate">
                    <h:selectBooleanCheckbox id="donate"
                        value="#{weighFamilyBacking.donateOnly}" />
                </h:outputLabel>
            </ul>
        </h:panelGroup>
        <h:commandButton
            actionListener="#{weighFamilyBacking.distributeWeights}"
            immediate="true" value="Redistribute" />
        <h:commandButton action="cancel" value="Cancel" />
        <h:commandButton action="#{weighFamilyBacking.save}" value="Save" />
    </h:form>

</ui:define>
</ui:composition>
</html>
更多信息

这是日志的转储,我在这里记录getLbs和getOz。。您可以看到WebWeight对象上的getLbs或getOz在渲染阶段没有被调用

 - BEFORE INVOKE_APPLICATION 5
net.halo3.hcbb.registration.WebWeight@12d58dfe
net.halo3.hcbb.registration.WebWeight@12d58dfe getLbz: 0
net.halo3.hcbb.registration.WebWeight@12d58dfe getOz:0
net.halo3.hcbb.registration.WebWeight@25d285b
net.halo3.hcbb.registration.WebWeight@25d285b getLbz: 0
net.halo3.hcbb.registration.WebWeight@25d285b getOz:0
net.halo3.hcbb.registration.WebWeight@6c317dc9
net.halo3.hcbb.registration.WebWeight@6c317dc9 getLbz: 0
net.halo3.hcbb.registration.WebWeight@6c317dc9 getOz:0 
- AFTER INVOKE_APPLICATION 5
- BEFORE RENDER_RESPONSE 6
- AFTER RENDER_RESPONSE 6

问题是您已经在命令按钮上设置了immediate属性

这将导致在APPLY_请求阶段调用您的操作侦听器,但另外,不会调用UPDATE_MODEL,当视图再次呈现时,它将呈现仍在输入组件中的值(组件在JSF中是有状态的)

有关更多详细信息,请参见此:

由于没有任何验证器连接到输入组件,因此最简单的解决方案可能是删除immediate属性


(主题之外,但我注意到你的支持bean是随机排序的,这使得它有点难以阅读。在Java/JSF中,你通常在最开始的时候就放置实例变量,然后是构造函数、后期构造方法、preRenderView事件处理程序等,所以类从上到下阅读)

事实证明,问题出在xhtml的某些方面。当我把它全部清理干净,开始简单的工作时,它开始工作了。我想可能是outputLabels或PanelGroup。

一些代码将有助于更好地理解您的错误。我支持BalusC。您想要做的是一个完全正常的用例,如果在
INVOKE\u应用程序
阶段调用了动作侦听器,那么它应该可以正常工作。此时将不会“放回”更多值,并且在渲染开始之前,此方法处于完全控制状态。那么,给我们看看代码。添加了一些示例代码。。我的主要问题是UI输入对象是否在调用应用程序阶段之后从对象中获取其值?我认为@Arjan已经提到过这种情况。在getters内部执行业务逻辑也不值得奖励。感谢您的反馈。我删除了即时标志,现在,当我单击“重新分发”时,选中了“仅捐赠”复选框,但权重值并没有像我预期的那样重置为“123”“456”。我将重新处理getter并重新组织代码。当我在尝试不同的解决方案时,它变得非常混乱。。巴卢斯感谢你在这方面的贡献。在学习JSF的过程中,我花了很多时间阅读您的回答……不确定是否相关,但我也得到了“表单组件需要在其祖先中有一个UIForm。建议:将必要的组件包含在”底部的警告。我不明白为什么,因为据我所知,它们是用h:form正确包装的。此外,我可以确认WebWeight对象没有被重新创建。在每次单击之间登录时,都有相同的地址。>在Getter中执行业务逻辑也不值得奖励。-你说得对!事实上,我的清单上有这样的话要说,但我忘了;)@OP:除了样式问题之外,需要记住的是,在JSF中可能多次调用getter。在他们身上尽可能少做。
BEFORE INVOKE_APPLICATION 5
net.halo3.hcbb.registration.WebWeight@2f6cd09f
net.halo3.hcbb.registration.WebWeight@10f48f0c
net.halo3.hcbb.registration.WebWeight@27db6586 
AFTER INVOKE_APPLICATION 5
BEFORE RENDER_RESPONSE 6
oz=456 lbs=123 object=net.halo3.hcbb.registration.WebWeight@2f6cd09f
oz=456 lbs=123 object=net.halo3.hcbb.registration.WebWeight@10f48f0c
oz=456 lbs=123 object=net.halo3.hcbb.registration.WebWeight@27db6586
AFTER RENDER_RESPONSE 6
 - BEFORE INVOKE_APPLICATION 5
net.halo3.hcbb.registration.WebWeight@12d58dfe
net.halo3.hcbb.registration.WebWeight@12d58dfe getLbz: 0
net.halo3.hcbb.registration.WebWeight@12d58dfe getOz:0
net.halo3.hcbb.registration.WebWeight@25d285b
net.halo3.hcbb.registration.WebWeight@25d285b getLbz: 0
net.halo3.hcbb.registration.WebWeight@25d285b getOz:0
net.halo3.hcbb.registration.WebWeight@6c317dc9
net.halo3.hcbb.registration.WebWeight@6c317dc9 getLbz: 0
net.halo3.hcbb.registration.WebWeight@6c317dc9 getOz:0 
- AFTER INVOKE_APPLICATION 5
- BEFORE RENDER_RESPONSE 6
- AFTER RENDER_RESPONSE 6