facelets组件的自动生成的id

时间:2011-01-05 10:19:57

标签: java jsf jstl facelets

我们使用facelets创建一些自定义的ajaxy组件。我们想要从默认组件模仿的行为之一是id是可选的,如果没有传递则生成id。我已经可以这样做了:

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

我使用JBoss el来调用支持方法(也可以使用el函数):

public class JsfSupport {

  public String generateId(String id) {

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

}

问题是,如果我在组件中的javascript代码中需要该ID,我需要再次检索它。所以我想我可以做到以下几点:

<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>

但这不起作用。无论如何id都会重新生成,我会得到两个不同的id。 关于什么是理想的方法的任何想法?

1 个答案:

答案 0 :(得分:1)

Facelets中的

<c:set>表示别名,而不是JSP中的赋值。因此,#{id}的每次使用都会转换为对#{jsfSupport.generateId(id)}的单独调用,从而导致您描述的问题。

您可以编写自己的<c:set>标记版本,该标记仅评估传递的表达式一次,并保存返回的值:

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));
    }
}