JSF 2 Update Component Outside of Form and Outside of Facelet
Asked Answered
T

2

7

I have a form in the <ui:insert name="content" /> When I save the data with a p:commandButton I can update the form and things within the <ui:insert name="content" />. But I am having trouble figuring out how to update components in the <ui:include src="/sections/menus/topMenu.xhtml"/>

Inside the topmenu I have a subview for a panel with links that get rendered depending on whether a person is logged in or not. when they are logged in I show their username. If I update the user name in the content part of the template, I want to update the ui so that the name in the menu also updates without a page refresh. But that is a fallback I can use too. Refresh the page after update. But would rather not. I'll post more code if you want but trying to keep it to a minimum to start.

  <h:body>
    <div id="wrap">
      <div title="Container">
          <ui:include src="/sections/base/header.xhtml"/>
        </div><!-- End of Banner -->

        <div id="baseTemplateTopMenu" title="Menu">
          <ui:include src="/sections/menus/topMenu.xhtml"/>
        </div><!-- End of Menu -->

        <div id="sbt_contentbody"> 

            <div title="Left Column">
              <ui:include src="/sections/base/leftsidebar.xhtml"/>
            </div> <!-- End of Left Column -->
            <div title="Content Column">
              <ui:insert name="content" />
            </div><!-- End of Centre Column -->
            <div title="Right Column">
              <ui:include src="/sections/base/rightsidebar.xhtml"/>
            </div><!-- End of Right Column -->

        </div>
        <div id="footer" title="Footer" class ="container">
          <ui:include src="/sections/base/footer.xhtml"/>
        </div><!-- End of Footer -->

      </div><!-- End of Container -->
  </h:body>

Below is the p:commandButton that saves the user info

<p:commandButton id="id_SubmitUserInfoPrefs"
                    value="Update"
                    action="#{userPreferences.updateUserInfo()}" styleClass="bottom_margin_2em top_margin_2em">
    <f:ajax execute="@form" render="@form :topMenuLoginView:topMenuLoginForm" />
<!-- tried adding 'update=":"topMenuLoginView:topMenuLoginForm"' as well. -->

Below is in the menu part of the template.

<f:subview id="topMenuLoginView">
    <h:form id="topMenuLoginForm" prependId="false">
        <ul>
            <h:panelGroup id="loginPanel" rendered="#{!user.loggedIn}">
                <li><h:outputLink value="javascript:void(0)" onclick="topMenuLoginDialog.show()" 
                                    title="login" styleClass="loginpanelclass">Log In</h:outputLink></li>
                <li><h:link value="Register" outcome="/registration/register.xhtml" /></li>
            </h:panelGroup>
            <h:panelGroup id="logoutPanel" rendered="#{user.loggedIn}">
                <li><h:link value="#{user.nickname}" outcome="#{navigationprops.userprefs}" /> </li>
                <li><p:commandLink action="#{webAuthenticationBean.logout}" 
                                    update=":topMenuLoginView:topMenuLoginForm">
                        Logout
                    </p:commandLink>
                </li>
            </h:panelGroup>
        </ul>
    </h:form>
</f:subview>
Teetotalism answered 27/8, 2012 at 4:33 Comment(2)
how about render="@form :topMenuLoginForm" and just remove the <f:subview id="topMenuLoginView"> from that page?Cohesive
Will try that a bit later. I need to get moving and have just chosen to refresh the page on completion. I'll refactor later this week.Teetotalism
T
9

The general idea of referring to an element by ID is as following:

Lets say we've got an element <p:commandButton>.

When the element is given no id JSF generates one:

<button name="j_idt191" id="j_idt191" ....

If an element is nested in a container element like a form, JSF prefixes the ID with the ID of the form:

JSF:

<h:form>
    <p:commandButton/>
</h:form>

HTML:

<form id="j_idt48">
    <button name="j_idt48:j_idt191" id="j_idt48:j_idt191" ....
</form>

When there is an element in another container you need to reference from the root element. This can be done using a ":" in front of the ID. Here is an example:

<p:commandButton id="button1" update=":form:button2" ...

<h:form id="form">
    <p:commandButton id="button2" update=":button1" ...
</h:form>

If you're not sure what ID JSF has assigned to your element, use something like FireBug to inspect the element and discover it's ID.

As far as your code, I don't think <f:subview> is generating a container element, thus you need to reference topMenuLoginForm using update=":topMenuLoginForm".


That being said, if you want to update an element using AJAX, use the update attribute. See my example above.

Titania answered 27/8, 2012 at 21:48 Comment(1)
I tried the update route as well. I am pretty sure I tried only topmenuloginform as well. I already access the topmenuloginform from a different form (the one used to actually log someone in), but that form is located in the same topmenu file as the topmenuloginform. I'll give it another go because maybe it is in my head that I tried it for some reason. Later in the week though, had to go around it to get some things done. Will refactor later in the week. I'm just refreshing the page on completion to get it working for now.Teetotalism
S
2

to Update Component Outside of Form

<p:gmap center="36.890257,30.707417" zoom="13" type="ROADMAP" 
                style="width:600px;height:400px"
                model="#{mapBean.simpleModel}"
                onPointClick="handlePointClick(event);"
                widgetVar="cliMap" fitBounds="true"
                id="map">
            <p:ajax event="overlaySelect" listener="#{mapBean.onMarkerSelect}"  />
        </p:gmap>

        <p:dialog widgetVar="dlg" showEffect="fade">
            <h:form prependId="false" id="formnew">
                <h:panelGrid columns="2">
                    <f:facet name="header">
                        <p:outputLabel value="New Point"/>
                    </f:facet>
                    <h:outputLabel for="title" value="Title:" />
                    <p:inputText id="title" value="#{mapBean.title}" />

                    <f:facet name="footer">
                        <p:commandButton value="Add" actionListener="#{mapBean.newPoint()}" update=":map" oncomplete="markerAddComplete()" />
                        <p:commandButton value="Cancel" onclick="return cancel()" />
                    </f:facet>
                </h:panelGrid>
                <h:inputHidden id="Nlat" value="#{mapBean.lat}"  />
                <h:inputHidden id="Nlng" value="#{mapBean.lng}" />

            </h:form>
        </p:dialog>

i used update=":map" to update the google map out of the form Using Primefaces

Streptokinase answered 22/5, 2014 at 8:26 Comment(1)
This is a rather different situation, where there is no structure (with components loaded ui:include tag, for instance) like the one referred in the question.Tensimeter

© 2022 - 2024 — McMap. All rights reserved.