2

I've created a custom Facelet tag. I would like the ID to fall back to the default j_idtXxx just like if you would have left out the entire ID attribute when it is not set in the XHTML.

So, I would like <my:tag id="fiets"/> to be rendered as <span id="fiets"/>.

But, <my:tag/> should be rendered as <span id="j_idtXxx"/>.

If I would use <h:anyTag id="#{id}"/> in my tag file, it simply fails on the empty ID attribute. Is there any way to be rendered as a default generated ID? I would like to create something like:

<c:set var="id" value="#{empty id ? USE_DEFAULT : id}" />

But I don't know what to use at USE_DEFAULT.

Community
  • 1
  • 1
Jasper de Vries
  • 19,370
  • 6
  • 64
  • 102

1 Answers1

2

The functionality is available by UIViewRoot#createUniqueId(). The current UIViewRoot instance is in EL available as implicit object #{view}.

So, this should do:

<c:set var="id" value="#{empty id ? view.createUniqueId() : id}" />
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thanks for the prompt answer. In my case this leads to an exception: `Component ID main:j_id6 has already been found in the view`. – Jasper de Vries Apr 07 '17 at 10:24
  • That could happen if it has a `scope="request"` or wider and there are multiple instances of same tag. – BalusC Apr 07 '17 at 10:51
  • I removed `` and just used `id="#{empty id ? view.createUniqueId() : id}"`. Now it works. – Jasper de Vries Apr 07 '17 at 11:03
  • Strange. It defaults to "none" scope (i.e. store nowhere and evaluate every time). Which JSF impl/version are you using? – BalusC Apr 07 '17 at 11:59
  • I'm using Mojarra 2.2.7 – Jasper de Vries Apr 07 '17 at 12:03
  • This ignores current naming container context. If `my:tag` is inserted e.g. into a form, then you need to ask the form component for a unique id. See what `javax.faces.component.UIComponentBase.getClientId(FacesContext)` is doing with the `namingContainerAncestor`. – Vsevolod Golovanov Sep 11 '18 at 18:09
  • `This ignores current naming container context`, but at Restore View the current component doesn't have parent specified yet, so that failed. And with `view.createUniqueId` the id often changes after a postback, which can be a bit of a problem. – Vsevolod Golovanov Oct 10 '18 at 21:15
  • @VsevolodGolovanov that only happens if component tree structure changes during postback, which indicates another problem. E.g. JSTL tags not being correctly used, or build time dependent variables not being in correct scope. – BalusC Oct 11 '18 at 16:08
  • @BalusC, the id changes from the viewroot generated "j_id" to the "j_idt" form. I think, that's not a structure changing thing, that's a state saving thing. We're using server side state saving with partial disabled, so it's a path less trodden... – Vsevolod Golovanov Oct 11 '18 at 19:00