我们使用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。 关于什么是理想的方法的任何想法?
答案 0 :(得分:1)
<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));
}
}