Can you update an h:outputLabel from a p:ajax listener?

后端 未结 2 670
迷失自我
迷失自我 2020-11-30 11:47

I\'m trying to use a p:ajax tag and then in that listener, i\'m setting a value called \"periodRendered\". then i\'m trying to update an h:outputLabel tag via an update from

相关标签:
2条回答
  • 2020-11-30 12:27

    I'm not sure the reason for this behavior, but I'm putting money on the fact that p:ajax is going to require an active target for the update to work. Here's an example of it working/not working:

    <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>
    

    //Bean...

    @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;
        }
    }
    

    I don't have the time to dig into this one, but from a quick look (again QUICK) in the debugger it looks like it doesn't find the ID (it isn't rendered) so it doesn't get the update. Why? I'm not sure--the easy workaround is to place it inside something you can update (p:outputPanel) and render it as a span, then your code should work. Is this acceptable? Not really...

    If you can deal with a full form update the following will work as well ->

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

    Since you're targeting the enclosing form it updates all the children. If I was doing this, that is the workaround I'd use. It isn't a lot of data and it is a heck of a lot cleaner. I'm not sure if this a bug or a feature. It feels buggy though.

    Short answer: yes you can target a label. Long answer: you can't target one that isn't rendered. I really hope this helps.

    0 讨论(0)
  • 2020-11-30 12:39

    You cannot update elements which are not rendered , rendered=false "is a JSF way to" to remove elements from the DOM Tree ,

    its not like css display:none or visibility:hidden <- this two will keep the elements in the DOM tree but hidden , while the JSF rendered=false wont even render (keep) the element in the DOM tree (you wont even see it in the "view source" of the page)

    So in you case you need to wrap the outputLabel with `panelGroup' and update the id of the wrapper

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

    and refer to the wrapper (which always be in the DOM tree) id in the <p:ajax update attribute, like this:

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

    Another solution would be the update the entire form like this <p:ajax update="@form" ... that way you don't need the wrap the outputLabel

    regarding your comment question

    how does @form update the un-rendered elements, but targeting them directly through id's does not?

    You can't target an element in update which is not present in the page (rendered=false) "its not there"

    But when you use update="@form" or update="someWrapperID" the form/wrapper "re evaluates" all its inner elements , including the ones with rendered="#{someBean.someCondition}" and the condition gets "re evaluated" so if it result to true the elemet will be displayed...

    0 讨论(0)
提交回复
热议问题