What's the difference between #{cc.foo} and #{cc.attrs.foo}? - jsf

I'm trying to add something to a composite component somebody else created and there is a #{cc.foo} in there. I can't seem to find where foo is defined, even doing a grep over the entire codebase.
What's the difference between cc.attrs.foo and cc.foo in general?
EDIT I found it in some jar, therefore I didn't see it in the search. Still the question generally remains. Thanks

What exactly is foo? Composite components (as other UIComponents) have certain properties predefined: for example, #{cc.rendered} or #{cc.clientId} are defined by the Java EE spec, not the user, so they are always available within composite components.
In general, #{cc.whatever} will be properties of the component itself: its component ID #{cc.id}, its client ID (i.e. what's rendered as the id attribute of the HTML tag) #{cc.clientID}, its parent component #{cc.parent}, etc. These are provided by Java EE. On the other hand, #{cc.attrs.whatever} are provided by the component developer: they will be the named attributes of the composite component: for each <composite:attribute name="myAttribute" ... /> in the <composite:interface> section of the composite component file, there will be a #{cc.attrs.myAttribute} available to use in the <composite:implmenentation> section of the composte component file.

Related

JSF composite component interface tag "expert" property. What is it for?

Regarding the <composite:interface> tag for JSF composite components, what is the use of the "expert" property of the (interface tag](https://docs.oracle.com/javaee/7/javaserver-faces-2-2/vdldocs-facelets/cc/interface.html)?
The description is awfully vague and I found no references to its use or documentation online.
What is its purpose and usage?
I've scanned the Mojarra source code. It's ultimately set in java.beans.FeatureDescriptor class.
But it's in turn not really anywhere used.
With this I conclude that it's just unused inherited logic. The same applies to dislayName, shortDescription, hidden and preferred attributes. Only the name and componentType are actually concretely used.
The unused attributes are at most only used by tooling such as IDEs like Eclipse and Netbeans so that they can parse and show the right labels and tooltips here and there when working with (custom) composite components.

How to find an component ID including the composite component ID from backing bean

Our project using PF5.1, we have a dataTable in a composite component. So after page rendering. the dataTable's id kind of like j_idt123:tableForm:tableId.
We need to clear the table filter stuff before searching. I tried use the following code to find it in the backing bean but it returns null.
FacesContext.getCurrentInstance().getViewRoot().findComponent("tableId");
As this component will be used in different xhtml file, this "j_idt123" thing got changed every time. What will be the right way to get the table ?
"j_idt123" is a generated id for components which do not specify their own.
Just give the parent-container of "tableForm" an id.

How do I bind a composite component in JSF?

I have a composite component which is composed of other composite components. Now I would like to render only some of the child components within the parent component. From the Java EE tutorial I take it that I should probably bind my child components to some property of the backing bean for my parent component so that I can access their render attribute.
However, the NetBeans IDE does not know about a binding attribute for my composite components. So how am I supposed to do this?
Use case: The parent component is some wizard which should display only one of the child components at a time. Think of it as a poor man's tabbed view. I know there are libraries which provide ready-made components for this, but I do not want to add another dependency.
Netbeans is lying. That attribute is definitely supported on <ui:component>. Just use it and ignore the warning/error in the IDE. Or better, just use the rendered attribute; the need to conditionally render components is not a valid reason to prefer binding over rendered.

How to access a composite component's sibling via clientId

I have a composite component that bundles some input fields. The component will be used multiple times on a page and contains a button to copy the values of another of these components. For this I would need to access one of those siblings via its clientId as a target for an
<f:ajax execute=":XXX:siblingId" render="...">
My problem lies in constructing this ID. I have the name of the sibling and I can make sure that it is located in the same naming container as the component that contains the copy button, but I can't control the complete nesting hierarchy, so it might be :form:foo:bar:parent:child or just form:parent:child. So essentially I would want to get the prefix of the current composite component, but without the component's own ID and then attach the ID of the component from which to copy.
This is similar to these questions:
How to address the surrounding naming container in jsf
How to access the parent naming container of composite
However, both answers make use of PrimeFaces-sepcific features like #parent and widgetVar, which does not apply to my project.
When experimenting with EL's implicit objects I basically tried the same things as the poster of the second question - with the same results: cc.parent.clientId is always empty. I also tried cc.namingContainer.clientId and some combinations of the two, alas - no success. Especially the fact that parent does not work as expected confuses me...
So: Is there a component-library-agnostic way to access the "path" of containing naming containers for a composite component? How is the parent object supposed to work, especially: when can we use it and when not?
PS: I was thinking about using the composite's full clientId and then trimming its actual ID with fn:split, however, if there was a more direct way I'd be happy to use it.
The #{cc.parent} resolves to UIComponent#getCompositeComponentParent() which returns the closest parent composite component. In other words, it returns only non-null when the composite component is by itself nested in another composite component.
The #{cc.namingContainer} simply refers to #{cc} itself, fully conform as specified in UIComponent#getNamingContainer():
Starting with "this", return the closest component in the ancestry that is a NamingContainer or null if none can be found.
Composite components namely implicitly implement NamingContainer themselves.
So your attempts unfortunately won't work. I also do not see any "standard API" ways to achieve the concrete functional requirement. The CompositeComponentAttributesELResolver causes that the #{cc.parent} doesn't resolve to UIComponent#getParent() which is what you ultimately want.
You can however provide a custom UIComponent implementation for the composite which adds an extra getter with an unique name which in turn properly delegates to UIComponent#getParent().
Here's a kickoff example:
#FacesComponent("myComposite")
public class MyComposite extends UINamingContainer {
public UIComponent getParentComponent() {
return super.getParent();
}
}
If you register it as follows in the composite interface:
<cc:interface componentType="myComposite">
then you'll be able to use
#{cc.parentComponent.clientId}
to get the client ID of the real parent UIComponent.
Ultimately you should be able to use the following construct to refer the sibling:
process=":#{cc.parentComponent.clientId}:siblingId"

Is the ID generated by JSF guaranteed to be the same across different versions and implementations?

We are about to write a full set of tests for one of our JSF applications using Selenium.
So far, it seems that there are two preferred approaches to uniquely identify each element: by ID or using a unique class name. The later is really a hack and doesn't make sense semantically. The former is the right approach, but the element IDs are generated by JSF.
All the different JSF implementations I've seen seem to be using the same approach: use the parent element as the namespace and then concatenate the element ID using a colon. Fair enough.
The question is: do you know if this is guaranteed in some part of the JSF specification? It'd be a real problem to find out later that we need to rewrite all the component selectors in the tests just because JSF x.y changed the way it generates the ID names.
Thanks!
JSF usually generated the ID of components, if ID attribute is not explicitly mentioned.
It will be generated in the format j_idXXX (XXX will be number incremented)
<h:form id="LoginForm">
<h:inputText id="userName" .../>
</h:form>
for this inputText the id will be formed as LoginForm:userName and if id is not mentioned explicitly,then it will be formed something like LoginForm:j_id15
This is mentioned in JSF specification in section 3.1.6, But the exact format is not specified though.
The clientId is generated using this method UIComponent.getClientId(); Follow this link UIComponent
Is the ID generated by JSF guaranteed to be the same across different versions and implementations?
No. You've to explicitly specify the component ID on the UIInput component of interest and all of its parent UINamingContainer components such as <h:form>, <ui:repeat>, <h:dataTable>, etc yourself. Those IDs will by default be woodstocked using separator character :.
However, the separator character is in turn configureable since JSF 2.0. So, if you change the separator character for your webapp from : to - or something, then you'd have to rewrite the selenium tests which are relying on the HTML element IDs.
From the JSF (2.1) spec:
The client identifier is derived from the component identifier
(or the result of calling UIViewRoot.createUniqueId() if there is
not one), and the client identifier of the closest parent component
that is a NamingContainer according to the algorithm specified
in the javadoc for UIComponent.getClientId(). The Renderer
associated with this component, if any, will then be asked to convert
this client identifier to a form appropriate for sending to the
client. The value returned from this method must be the same
throughout the lifetime of the component instance unless setId() is
called, in which case it will be recalculated by the next call to
getClientId().
Aside from the spec, 3rd party plugins can affect the client identifier (e.g. protlet bridge APIs)

Resources