Get id of parent naming container in template for in render / update attribute
Asked Answered
U

5

18

I have a template and in its Definition I use several forms and buttons.

The problem is the definition (define) xhtml file does not know the component hierarchy.

And for example I want to update the element "table2" in a different form in the same define file.

Template Insert:

<p:tabView id="nav"> <!-- nav -->
    <ui:insert name="content_nav">content navigation</ui:insert>
</p:tabView>

defines the first level of my hierarchy "nav"

Template define:

<ui:define name="content_nav">
    <h:form id="form1"> <!-- nav:form1 -->
        <h:dataTable id="table1"/> <!-- nav:form1:table1 -->
        <p:inputText value="#{bean.value}"/>
        <p:commandButton action="..." update="nav:form2:table2"/>
    </h:form>
    <h:form id="form2">
        <h:dataTable id="table2"/> <!-- nav:form2:table2 -->
        <!-- other elements -->
    </h:form>
</ui:define>

In my define part I don't want to know "nav"!

How can I do this? or how can I move one naming component upwards?, or save the highest parent complete id in a variable?

sometimes i saw something like:

update=":table2"

But I could not find any informations about this?, the JavaEE 6 documentation just mentions the @ keywords.

Ubangishari answered 13/1, 2012 at 7:11 Comment(0)
S
52

Ugly, but this should work out for you:

<p:commandButton action="..." update=":#{component.namingContainer.parent.namingContainer.clientId}:form2:table2" />

As you're already using PrimeFaces, an alternative is to use #{p:component(componentId)}, this helper function scans the entire view root for a component with the given ID and then returns its client ID:

<p:commandButton action="..." update=":#{p:component('table2')}" />
Shanel answered 13/1, 2012 at 12:59 Comment(7)
Thanks for your answer. #{component.namingContainer.parent.namingContainer.clientId} works fine. But I hoped for a more elegant solution (syntax sugar). Similar to "../" for folderstructures. Why did you still wrote a colon as a prefix? I am new to jsf so I ask. And I do not think its that ugly since using the unknown naming container clientId directly is more ugly since I could use that template multiple times. I think I will define myself a EL function to get the clientId of a sibling naming container.Ubangishari
The colon is the default NamingContainer separator character (which is overrideable by a context param though). When using it as prefix, it will be interpreted as "absolute" client ID, i.e. it's been resolved relative to the UIViewRoot instead of the current NamingContainer (which can be the composite, or datatable, or form, etc). As to the nicer solution, use p:component() function instead (or homebrew one yourself).Shanel
p:component doesnt work for me. I'm really sad with this JSF behavior. Nothing works.Fold
@MaikoID: Just press Ask Question with a decent SSCCE if you need help instead of sitting back doing nothing else than complaining and crying because you can't debug it yourself.Shanel
Great advice! It helped me with updating only specified component within an active tab in PrimeFaces TabView.Wiper
@Shanel does the same logic hold for datasource attribute of p:droppable ? I am struggling to map the correct datasource. Exact problem: stackoverflow.com/questions/46551952/…Timekeeper
@BalusC, once again a solution of yours saved my life: :#{p:component('..')} thingy is perfect. Your posts are a blessing! Thanks, mate!Anthropology
T
1

ugly answer works well

update=":#{component.namingContainer.parent.namingContainer.clientId}:form2:table2

mainly more useful updating from opened dialog to parent datatable

Turpin answered 28/2, 2013 at 15:21 Comment(0)
M
1

You may use binding attribute to declare EL variable bound to JSF component. Then you may access absolute client id of this component by using javax.faces.component.UIComponent.getClientId(). See example below:

<t:selectOneRadio 
   id="yourId"
   layout="spread"
   value="#{yourBean.value}"
   binding="#{yourIdComponent}">
       <f:selectItems value="#{someBean.values}" />
</t:selectOneRadio>
<h:outputText>
   <t:radio for=":#{yourIdComponent.clientId}" index="0" />
</h:outputText>
Muse answered 25/4, 2016 at 10:5 Comment(0)
D
0

Try this:

<h:commandButton value="Click me">
    <f:ajax event="click" render="table" />
</h:commandButton>
Dorolice answered 13/1, 2012 at 7:58 Comment(3)
I wasn't precise enough. I want to update a particular element by its id, since not all elements are in the same form. I edited my post to make it clear. What does the @table do precisely? If both elements are siblings I could just use render="table" without @?Ubangishari
You could to use render="table".Dorolice
What is render="table"...?Foraminifer
R
0

Additionally to the solutions above I had the problem, that I had to dynamically generate the to-be-updated components (many) based on server-side logic (with maybe harder to find out nesting).

So the solution on the server-side is an equivalent to update=":#{p:component('table2')}"1 which uses org.primefaces.util.ComponentUtils.findComponentClientId( String designId ):

// UiPnlSubId is an enum containing all the ids used within the webapp xhtml.
// It could easily be substituted by a string list or similar.
public static String getCompListSpaced( List< UiPnlSubId > compIds ) {

    if ( compIds == null || compIds.isEmpty() )
        return "" ;
    StringBuffer sb = new StringBuffer( ":" ) ;
    for ( UiPnlSubId cid : compIds )
        sb.append( ComponentUtils.findComponentClientId( cid.name() ) ).append( " " ) ;
    return sb.deleteCharAt( sb.length() - 1 ).toString() ;  // delete suffixed space
}

called via some other method using it, e.g. like ... update="#{foo.getCompListComputed( 'triggeringCompId' )}".

1: first I tried without too much thinking to return public static String getCompListSpaced0() { return ":#{p:component('table2')}" ; } in an ... update="#{foo.getCompListSpaced0()} expression, which of course (after thinking about how the framework works :) ) is not resolved (returned as is) and may cause the issues with it some users experienced. Also my Eclipse / JBoss Tools environment suggested to write :#{p.component('table2')} ("." instead of ":") which did not help - of course.

Romanov answered 21/1, 2016 at 13:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.