5

我正在尝试使用 ap: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}"> 
4

2 回答 2

10

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

它不像cssdisplay:nonevisibility:hidden <-这两个将保留DOM树中的元素但隐藏,而JSFrendered=false甚至不会渲染(保留)DOM树中的元素(你甚至不会在页面的“查看源代码”中看到它)

因此,在您的情况下,您需要outputLabel使用“panelGroup”包装并更新包装器的 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页面中不存在的元素(rendered=false)“它不存在”

但是,当您使用update="@form"update="someWrapperID"表单/包装器“重新评估”其所有内部元素时,包括那些带有rendered="#{someBean.someCondition}"并且条件被“重新评估”的元素,因此如果它导致元素true将被显示......

于 2012-04-29T06:41:42.137 回答
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;
    }
}

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

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

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

由于您的目标是封闭表单,因此它会更新所有子表单。如果我这样做,那就是我会使用的解决方法。它不是很多数据,而且非常干净。我不确定这是错误还是功能。不过感觉很坑。

简短的回答:是的,您可以定位标签。长答案:您不能针对未渲染的目标。我真的希望这会有所帮助。

于 2012-04-27T22:11:17.883 回答