1

In my case I want to refresh the component with ID baseTab. It is itself contained if form main and tabView tabs. The absolute reference to the component is main:tabs:baseTab. and this is what I need to refer to for example in update attribute:

 <p:commandButton update="main:tabs:baseTab"/>

The problem with such full ID is that it is long and can be easily change when I change something in component hierarchy. The ID baseTab is itself unique so I should be, at least theoretically, able to refer this component direcly. But how I can do that?

What is the syntax to refer the component via unique ID? I've tried the following:

  • :baseTab
  • baseTab
  • main:baseTab
  • :tabs:baseTab

And none of that was working, each was causing the page error that such component does not exist....

partlov
  • 13,789
  • 6
  • 63
  • 82
Danubian Sailor
  • 1
  • 38
  • 145
  • 223
  • possible duplicate of [How to reference components in JSF ajax? Cannot find component with identifier "foo" in view](http://stackoverflow.com/a/8644762). You need `:main:tabs:baseTab`. – BalusC Jan 09 '13 at 14:03
  • You'll only be able to directly refer to a component by ID, they have to have the same parent form at the very least. I would imagine this has some performance impact though, the Dom processor having to comb thru the DOM tree for an id as against a direct reference – kolossus Jan 09 '13 at 14:10
  • It wouldn't have anything to do with DOM performance. The whole jQuery is based on DOM search and the search by ID, unique or not, is extremally fast operation. – Danubian Sailor Jan 09 '13 at 14:14
  • Where is your `commandButton` in this hierarchy? Is it in that tab? – partlov Jan 09 '13 at 14:41
  • No, it is somewhere in the mainForm – Danubian Sailor Jan 09 '13 at 14:46
  • @BallusC the question you refer has generic character, how the name resolving works, and my question is about the selector for referring via absolute ID. In jQuery, for example, it is done with #. After reading your answer I've understood only that selector : is for relative reference. The accepted answer for my question would be either that there is no such selector (with some referrence for available selectors) or the work-around, such as that by @McDowell) – Danubian Sailor Jan 09 '13 at 16:06
  • Try `@B[tab]` the next time. You misspelling caused that I wasn't notified about this comment reply. Well, perhaps [PFS](http://www.primefaces.org/showcase/ui/selectors.jsf) is something you're looking for? Still this is too much a non-constructive question. One may vote for PFS, other may vote for binding, again other may vote for just standard JSF way. Meh :) – BalusC Jan 09 '13 at 21:56

2 Answers2

2

I can see the value in not making this reference depend on the component tree structure.

It should be possible to leverage the component binding for this because update can take a ValueExpression.

Define a map in request scope using (for example) a faces-config.xml:

<managed-bean>
  <managed-bean-name>bind</managed-bean-name>
  <managed-bean-class>java.util.HashMap</managed-bean-class>
  <managed-bean-scope>request</managed-bean-scope>
</managed-bean>

Bind the target to the map:

<h:foo binding="#{bind.someIdForBinding}" />

Reference this control's client identifier in your button:

<p:commandButton update=":#{bind.someIdForBinding.clientId}"/>

The target component will be put into the binding map when the tree is created/restored.

Note that this code is untested.

McDowell
  • 107,573
  • 31
  • 204
  • 267
  • It is interesting approach, but it requires creating bean only to store bindings. It don't makes the references shorter anyway, but maybe when the component structure is very deep and very dynamic, it would be inevitable. – Danubian Sailor Jan 09 '13 at 15:59
  • McDowell, the `update` attribute still needs to be prefixed with `:` in order to make it absolute. It's namely not part of the client ID. – BalusC Jan 09 '13 at 16:15
  • @BalusC Ah. Amended; again, no idea if this works in practice. – McDowell Jan 09 '13 at 16:21
  • McDowell, yes, it works in practice. I've even answered this approach several times before. The map bean is by the way not mandatory, but it makes the code more self documenting (I would however rather call it `components`, not `bind`). – BalusC Jan 09 '13 at 16:22
  • @lechlukasz The point is not to make expressions shorter; it is to stop tree structure changes affecting the reference. You could avoid creating a bean by binding directly to the request map (e.g. `#{requestScope.someIdForBinding}`) but this increases the chance of a collision with some other request-scope artefact. – McDowell Jan 09 '13 at 16:24
  • McDowell, even the `#{requestScope}` reference is not mandatory which makes it yet shorter. See also e.g. http://stackoverflow.com/questions/8168302/jsf-component-binding-without-bean-property and http://stackoverflow.com/questions/7666631/jsf-fajax-cannot-locate-component-on-context – BalusC Jan 09 '13 at 16:25
  • However, the shortest would be good selectors such as in jQuery ;) – Danubian Sailor Jan 09 '13 at 16:48
0

Don't think it is possible unless you components are in the same parent.

roel
  • 2,005
  • 3
  • 26
  • 41