0

In JSF 2.2, I have a custom composite component which wraps a vanilla component (let's say a h:commandLink).

Is it possible to add passthrough attributes on my composite component and pass them back to the wrapped component?

Something like this (it's an example, don't bother about its uselessness):

Declaration of my:commandLink:

<cc:interface>
    <cc:attribute name="text" type="java.lang.String" />
</cc:interface>

<cc:implementation>
    <h:commandLink a:magicInsertionOfAllThePassThroughAttributes>
        #{cc.attrs.text}
    </h:commandLink>
</cc:implementation>

Use of my:commandLink:

<my:commandLink text="oh no" a:data-something="…" a:data-otherthing="…" />
Vasil Lukach
  • 3,658
  • 3
  • 31
  • 40
Xavier Portebois
  • 3,354
  • 6
  • 33
  • 53
  • Styleclass and title are existing attributes on the commandLink. Are you sure you mean 'passThrough' in the JSF 2.2 sense of the word? Or do you just want to be able to have a dynamic number of attributes on your `myCommandLink` that all automatically mapped to the existing attributes of the `h:commandLink`? – Kukeltje Mar 30 '18 at 09:25
  • My example was pretty bad, I modified it with more exotic attributes. The purpose is indeed to map all unknown attributes for `my:commandLink` to the wrapped `h:commandLink` – Xavier Portebois Mar 30 '18 at 11:13
  • I've been googling a little and did not find something easy yet (not something complex either). But do you have a 'fixed' list of allowed attributes on the composite or can you define them (would be good for code completion too). If not I think you need to add a Custom component class : https://docs.oracle.com/javaee/7/tutorial/jsf-custom004.htm#BNAVU. If you can, I think I have a 'solution' – Kukeltje Mar 30 '18 at 11:30
  • The purpose here is to handle any passthrough attribute (lots of `data-` for jQuery behaviors, for example). I didn't find anything useful on google even with a component java class. I'm curious to know what you find :) – Xavier Portebois Mar 30 '18 at 11:55
  • Oh, I should have read your link before. You're thinking of getting the `UIComponent` from the java class, and then writing all attributes found with `getAttributes()` ? I should give it a try. – Xavier Portebois Mar 30 '18 at 11:57
  • 1
    Yep... But maybe add checking which ones are the passthough...But explicitly defining the attributes on your component (without the data-prefix) is good too so you can have code completion... in your ide and in the custom component you can add all them via the `f:passThroughAttribute` tag and add the `data-` prefix to them. (there is a `f:passTroughAttributes` too (plural) but I did not find a `cc.passThroughAttrs` anywhere – Kukeltje Mar 30 '18 at 12:21

2 Answers2

2

So, following @Kukeltje comments, I managed to do something with a custom composite component backing class:

@FacesComponent("PassThrough")
public class PassThroughComponent extends Component
{
    @Override
    public void encodeBegin(FacesContext facesContext) throws IOException
    {
        super.encodeBegin(facesContext);
        findComponent("pass").getPassThroughAttributes().putAll(getPassThroughAttributes());
    }
}

With a DOM element bearing a id='pass' in my component, I can pass the attributes to it.

Alas, Eclipse doesn't understand the trick, and triggers warnings seeing all these "unknown attribute 'a:something'".

I truly wonder how Primefaces components manage to avoid that.

Xavier Portebois
  • 3,354
  • 6
  • 33
  • 53
  • PrimeFaces components are real components not composite ones. That is why I said to explicitly define them and if your namespace is good for the composite attributes eclipse should not complain – Kukeltje Mar 30 '18 at 17:22
1

I think the JSF API is missing a helper for this. Maybe something like "insertPassthroughAttributes", similar like cc:insertChildren. Maybe OmniFaces can prototype this and we can add it to the next JSF specs. Someone should create a spec issue.

tandraschko
  • 2,291
  • 13
  • 13