你能从p:ajax监听器更新h:outputLabel吗?

时间:2012-04-27 21:22:42

标签: ajax jsf jsf-2 primefaces

我正在尝试使用p:ajax标签,然后在该监听器中,我设置了一个名为“periodRendered”的值。然后我试图通过p:ajax标签的更新来更新h:outputLabel标签。它没有更新ajaxily,我在想它是因为一个primefaces ajax标签无法更新标准的jsf outputLabel标签。

我的假设是否正确,是否有更合适的标签我应该使用而不是h:outputLabel?

<h:outputLabel for="addProgramTo" value="Add Program To" />
<p:selectOneMenu value="#{ppBacker.grantProgram.grant_project_id}" id="addProgramTo" size="1" styleClass="listBoxMedium">
    <p:ajax process=":addProgram:addProgramTo" update=":addProgram:periodGrid, :addProgram:periodLabel" event="change" listener="#{ppBacker.addProgramListener}" />
    <f:selectItems value="#{ppBacker.grantProjectDropDownList}" />
</p:selectOneMenu>            

<h:outputLabel for="period" value="Period" id="periodLabel" rendered="#{ppBacker.periodRendered}"> 

2 个答案:

答案 0 :(得分:10)

您无法更新未呈现的元素,rendered=false“是JSF方式”从DOM树中删除元素,

它不像css display:nonevisibility:hidden&lt; - 这两个将保留DOM树中的元素但隐藏,而JSF rendered=false甚至不会渲染(保留)元素在DOM树中(你甚至不会在页面的“查看源”中看到它)

所以在你的情况下你需要用{panelGroup'包装outputLabel并更新包装器的id

<h:panelGroup id="periodLabelWrapper">
    <h:outputLabel for="period" value="Period" id="periodLabel" rendered="#{ppBacker.periodRendered}">
</h:panelGroup>

并引用<p:ajax update属性中的包装器(始终位于DOM树中)id,如下所示:

<p:ajax process=":addProgram:addProgramTo" update=":addProgram:periodGrid, :addProgram:periodLabelWrapper" event="change" listener="#{ppBacker.addProgramListener}" />

另一种解决方案是更新整个表单,如<p:ajax update="@form" ...,这样你就不需要包裹outputLabel

关于您的评论问题

  

@form如何更新未渲染的元素,但是直接通过id瞄准它们呢?

您无法定位页面中不存在的update中的元素(呈现= false)“它不存在”

但是当您使用update="@form"update="someWrapperID"时,表单/包装“重新评估”其所有内部元素,包括具有rendered="#{someBean.someCondition}"的元素,并且条件得到“重新评估”,所以如果结果true将显示elemet ......

答案 1 :(得分:1)

我不确定这种行为的原因,但我正在投入p:ajax将要求更新生效的活动目标。这是一个工作/不工作的例子:

<h:body styleClass="center">
    <f:view contentType="text/html">
        <h:form id="test">
            <h:outputLabel for="addProgramTo" value="Add Program To: " />
            <h:selectOneMenu id="addProgramTo" value="#{testScope.target}">
            <p:ajax update=":test:periodLabel, :test:wrapper" event="change" process="@form">
            </p:ajax>
            <f:selectItems value="#{testScope.values}"/>
            </h:selectOneMenu>            
            <hr />
            <p:outputPanel id="wrapper">
                <h:outputLabel value="Works, has a target" rendered="#{testScope.timeToRender}"/>
            </p:outputPanel>
            <hr />
            <h:outputLabel value="does not work" id="periodLabel" rendered="#{testScope.timeToRender}" />   
        </h:form>
    </f:view>

</h:body>

//豆...

@ViewScoped
@ManagedBean(name = "testScope")
public class TestScope
{
    private String[] values = { "False", "What?", "True" };
    private String target = "Nothing";

    /**
     * @return the target
     */
    public String getTarget()
    {
        return target;
    }

    /**
     * @return the values
     */
    public String[] getValues()
    {
        System.out.println(values);
        return values;
    }

    public boolean isTimeToRender()
    {
        return "True".equals(target);
    }

    /**
     * @param target the target to set
     */
    public void setTarget(String target)
    {
        this.target = target;
    }
}

我没有时间深入研究这个,但是从调试器中快速查看(再次QUICK)看起来它没有找到ID(它没有渲染)所以它没有得到更新。为什么?我不确定 - 简单的解决方法是将它置于可以更新的内容(p:outputPanel)并将其呈现为跨度,然后您的代码应该可以工作。这可以接受吗?不是......

如果您可以处理完整表单更新,则以下内容也可以使用 - &gt;

<p:ajax update=":test" event="change" process="@form">

由于您要定位封闭表单,因此会更新所有子级。如果我这样做,那就是我使用的解决方法。这不是很多数据,而是更加清洁。我不确定这是一个错误还是一个功能。但是它感觉很麻烦。

简短回答:是的,您可以定位标签。答案很长:你不能瞄准一个没有渲染的人。我真的希望这会有所帮助。