Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Auto-generated ids for facelets components

We use facelets to create some custom ajaxy components. One of the behaviours we would like to mimic from the default components is that an id is optional, and an id is generated if it is not passed. I can already do it like this:

<ui:composition ...>
  <div class="myComponent" id="#{jsfSupport.generateId(id)}">
     ...
  </div>
</ui:composition>

I use JBoss el to call a support method (could use el functions as well):

public class JsfSupport {

  public String generateId(String id) {

    if (id==null || "".equals(id){
  return FacesContext.getCurrentInstance().getViewRoot().createUniqueId();
    }
    return id;
  }

}

The problem is that if I need that id somewhere in my javascript code in the component, I need to retrieve it again. So I thought I could do the following:

<ui:composition ...>
  <c:set var="id" value="#{jsfSupport.generateId(id)}" />
  <div class="myComponent" id="#{id}">
     ...
  </div>
  <script type="text/javascript">
    document.getElementById('#{id}');
  </script>
</ui:composition>

But that doesn't work. The id gets regenerated anyway and I get two different ones. Any ideas on what would be the ideal way to do this?

like image 989
Joeri Hendrickx Avatar asked Sep 16 '26 02:09

Joeri Hendrickx


1 Answers

<c:set> in Facelets means aliasing, not an assignment like in JSP. So every use of #{id} is translated into a separate call to #{jsfSupport.generateId(id)}, which results in problems you describe.

You could write your own version of <c:set> tag which would evaluate the passed expression only once, and save the returned value:

public class SetOnceHandler extends TagHandler
{
    private TagAttribute var;
    private TagAttribute value;

    public SetOnceHandler(TagConfig cfg) 
    {
        super(cfg);
        value = getRequiredAttribute("value");
        var = getRequiredAttribute("var");
    }

    public void apply(FaceletContext ctx, UIComponent parent) 
    {
        ctx.setAttribute(var.getValue(ctx), value.getObject(ctx));
    }
}
like image 92
socha23 Avatar answered Sep 17 '26 17:09

socha23



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!