16

I am updating a component via AJAX in JSF:

<h:form>
    <h:outputLink>Click me
        <f:ajax event="click" render=":messages" />
    </h:outputLink>
</h:form>

<h:messages id="messages" globalOnly="true" />

As the <h:messages /> resides outside <h:form /> I have to prefix the ID with colon (:). This works.

However, if I put this same code into a component and include that component into my page, the code fails. The reason is that :messages declaration refers to the root of the component hierarchy, while the <h:messages /> component that I want to update actually resides under my custom component, which resides under the page (so the location is of style :myComponent:messages.

Inside my component, how can I achieve the correct prefix to the <h:messages /> component? I know that I can manually assign ID to my component, and use that to prefix the reference (like :#{cc.attrs.id}:messages). However, I don't know at which level of component hierarchy this component lies, so the required prefix might even be something like :foo:bar:x:y:messages.

Tuukka Mustonen
  • 4,722
  • 9
  • 49
  • 79

2 Answers2

24

Seems like you can access the current prefix via Expression Language (EL) implicit objects (cc and component):

  • cc.clientId returns current composite component's prefix
  • component.clientId returns prefix for any current component.

For example, in a page, call some component via

<myComponent id="foo">

Inside this component, one can fetch the client IDs like this:

<h:outputText id="bar">
   <p>ClientId for the composite component: #{cc.clientId}</p>
   <p>ClientId for current any component: #{component.clientId}</p>
</h:outputText>

The following should print out as:

ClientId for the composite component: foo
ClientId for current any component: foo:bar

I got the pointer from blog post JSF: working with component identifiers (id/clientId). It states that this is a new feature for JSF 2.0. Before that one had to fetch the ID programmatically from a backing bean.

Tuukka Mustonen
  • 4,722
  • 9
  • 49
  • 79
0

@Tuukka Mustonen, thank you for your answer.

And if we need access some another id from the same "place" we could use:

<h:outputScript name="js/my-script.js"/>
<h:form id="myForm">
    <h:inputText id="aaa"
        onkeyup="myJSFunction(this.id)"
        value="..."
    />
    <h:inputText id="bbb"
        onkeyup="myJSFunction(aaa.id)"
        value="..."
    />
    <h:inputText id="ccc"
        onkeyup="myJSFunction('#component.parent.clientId.concat(':ccc')}')"
        value="..."
    />
    <h:inputText id="ddd"
        onkeyup="myJSFunction('#component.parent.clientId.concat(':aaa')}')"
        value="..."
    />
</h:form>

JavaScript function:

function myJSFunction(message) {
    window.alert(message)
}

Output on dialog window:

1) myForm:aaa

2) null

3) myForm:ccc

4) myForm:aaa

Note: so the 1st and 3th have the same output.

sasynkamil
  • 859
  • 2
  • 12
  • 23