考虑一个简单的复合组件,它采用某种动作参数 - 例如,一个简单的链接'美化'。我想'ajaxify'它。
<composite:interface>
<composite:attribute name="act" method-signature="java.lang.String action()"></composite:attribute>
<composite:attribute name="text" required="true"></composite:attribute>
<composite:clientBehavior name="click" event="action" targets="l"/> </composite:interface>
<composite:implementation>
<h:commandLink id="l" act="#{cc.attrs.action}" immediate="true"> <b>#{cc.attrs.text}</b> </h:commandLink> </composite:implementation>
我通过客户端行为公开事件。我这样用它:
<h:panelGroup layout="block" id="outside">
#{mybean.otherdata} <br/>
<mc:mylink text="Click click" action="#{mybean.click}" >
<f:ajax event="click" render="outside"/>"
</mc:mylink><br/>
</h:panelGroup>
你可以看到我想要做的事情:我想做一个ajax render outside 复合定义;只需将渲染设置为“outside”就会产生可怕的<f:ajax> contains an unknown id
错误。
是的,我知道命名容器,我知道我们可以用冒号前置并指定一个绝对路径,但这非常笨重。如果我将它包装在几个层中(这就是整点),我必须手动将这些引用链接在一起。
我是否可以制作某种相对引用,例如render="../outside"
来跳过对组件父容器的引用?
我用a4j做了一个jsf 1应用程序,这个模式在整个地方都被使用了。
答案 0 :(得分:7)
在JSF 2.0中,您可以在EL中使用隐式cc
和component
对象。要获取任何组件的完整客户端ID,请执行以下操作:
#{component.clientId}
要检索复合组件的客户端ID,请执行以下操作:
#{cc.clientId}
同样,您也可以使用#{cc.parent}
获取父级。在这种情况下,这可能是你想要的。如需更长时间的回答,请参阅Acquire full prefix for a component clientId inside naming containers with JSF 2.0。
答案 1 :(得分:1)
您可以使用render="@all"
或render="@form"
分别渲染所有内容或整个内容。
或者,您可以将要更新的绝对ID作为参数传递到组件中。这样可以保持灵活性,而不会不必要地重新渲染过多的页面。
答案 2 :(得分:1)
经过一些修补,这是一个解决方案:
在活动上放置一个听众:
<f:ajax event="click" listener="#{mycomp.listen}" render="#{mycomp.getParId('outside')}"/>"
实现:
public void listen(AjaxBehaviorEvent event) {
String clid=event.getComponent().getClientId();
StringTokenizer st=new StringTokenizer(clid,":");
StringBuilder sb=new StringBuilder(":");
for (int x=1;x<st.countTokens();x++)
{
sb.append(st.nextToken()).append(":");
}
parId=sb.toString();
}
public String getParId(String suff) {
//must precheck as id is prevalidated for existence. if not set yet set to form
if (parId==null)
{
return "@form";
}
return parId+suff;
}
即便如此,你为什么要这样做?
答案 3 :(得分:1)
我找到了一个更好的解决方案,我很高兴利用模板中的隐式“组件”映射。它允许使用../
文件系统表示法从复合组件返回基本相对映射。它可以扩展到更多处理,但这是我所需要的。它也适用于执行参数。
我要感谢我搞清楚!我又误解了什么?我不需要弄清楚这一点。
用法:
<mc:mylink text="Click me" action="#{blah.myaction}" render="../../pg" />
实现:
<composite:implementation>
<h:commandLink id="l" action="#{cc.attrs.action}" immediate="true">
<f:ajax render="#{pathProcessor.pathProcess(3, cc.attrs.render, component.clientId)}" />
#{simon.rand} . <b>#{cc.attrs.text}</b>
</h:commandLink>
.....
路径处理器方法:
public static String pathProcess(int currentNesting, String path, String clid) {
//System.out.println("clientid is "+clid);
//System.out.println("path is "+path);
//System.out.println("nesting is "+currentNesting);
String backTok="../";
String sepchar=":";
StringBuilder src=new StringBuilder(path);
int backs=0;
int inc=backTok.length();
while (src.indexOf(backTok,backs*inc)==backs*inc)
{
backs++;
}
//get rid of the source
String suffix=src.substring(backs*inc);
//add in internal nesting
backs+=(currentNesting-4);
StringTokenizer st=new StringTokenizer(clid,sepchar);
StringBuilder sb=new StringBuilder(sepchar);
for (int x=0;x<st.countTokens()-backs;x++)
{
sb.append(st.nextToken()).append(sepchar);
}
//backtracked path
String p=sb.toString();
//add suffix to the backtracked client path to get full absolute path
String abs=p+suffix;
return abs;
}
错误 - 我不知道为什么在计算背面时使用StringBuilder
,但你明白了。就是这样。
答案 4 :(得分:0)
cc.parent.cliendId解析父复合组件而不是直接父组件。 Obtaining the clientId of the parent of a JSF2 composite component
<composite:interface>
<cc:attribute name="render" type="java.lang.String" default="@this"/>
<cc:attribute name="action" method-signature="java.lang.String action()">
</composite:interface>
</composite:implementation>
<h:form>
<h:commandLink action="#{cc.attrs.action}" value="Click">
<f:ajax render="{cc.attr.render}" execute="@form"
</h:commandLink>
</h:form>
</composite:implementation>
因此,您可以自行决定要渲染哪个组件。
<h:panelGroup layout="block" id="outside">
#{mybean.otherdata}
<mc:mylink action="#{mybean.click}" render=":outside"/>
</h:panelGroup>