我想编写一个呈现javascript函数的自定义组件。它基本上表现为omnifaces onloadscript,它将使用其封闭父节点的客户端ID作为javascript函数的参数。
示例:
<h:panelGroup id="panel">
<my:component />
</h:panelGroup>
我已经开始编写这样的自定义组件,使用omnifaces onloadscript的实现作为指导。到目前为止看起来很好,但是当封闭父组件是复合组件时,我的自定义组件的实际父组件不是复合组件,而是insertChildren标签的父组件。
虽然这是有道理的,但这当然不是我想要的行为。
示例:
<my:composite id="panel">
<my:component />
</my:composite>
如果组合在其实现中使用了insertChildren标记,则my:component的父级的客户端ID不是“panel”。
问题:
答案 0 :(得分:0)
我终于找到了解决方案。
我已经实现了一个标记处理程序,它在处理标记时将一个UI组件添加到视图树中。请参阅以下代码中的注释。标签处理程序:
private final TagAttribute someAttribute;
@Override
public void apply(FaceletContext ctx, UIComponent parent) {
UIComponent parentOfParent = parent != null ? parent.getParent() : null;
// process only when created
if (parent != null && parentOfParent == null) {
Supplier<String> scriptProvider = getScriptProvider(ctx, parent);
ScriptComponent scriptComponent = new ScriptComponent(scriptProvider);
parent.getChildren().add(scriptComponent);
// note: the actual script is obtained when the ScriptComponent is rendered
}
}
protected Supplier<String> getScriptProvider(FaceletContext ctx, UIComponent target) {
// this is invoked when the tag is processed, so it's Ok for the EL context
String someValue = someAttribute.getValue(ctx);
return () -> {
// this is invoked by the script component when it is rendered,
// so we have the correct client ID even if the target is a composite component
String targetId = target.getClientId();
return String.format("myFunction('%s', '%s');", targetId, someValue);
};
}
UI组件:
private final Supplier<String> scriptProvider;
@Override
public void encodeBegin(FacesContext context) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.append("\n");
writer.startElement("script", this);
writer.append("\n");
String script = scriptProvider.get();
writer.append(script);
writer.append("\n");
}
@Override
public void encodeEnd(FacesContext context) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.endElement("script");
}