JSF 2.0 复合组件 - ajax 渲染参数 OUTSIDE 组件定义
Posted
技术标签:
【中文标题】JSF 2.0 复合组件 - ajax 渲染参数 OUTSIDE 组件定义【英文标题】:JSF 2.0 Composite components - ajax render parameter OUTSIDE component definition 【发布时间】:2011-03-06 05:02:13 【问题描述】:考虑一个简单的复合组件,它采用某种动作参数 - 例如,一个简单的链接“美化器”。我想“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渲染在复合定义之外;只需将渲染设置为“外部”就会出现可怕的<f:ajax> contains an unknown id
错误。
是的,我知道命名容器,而且我知道我们可以在前面加上一个冒号并指定一个绝对路径,但这很笨拙。如果我将它包裹在更多的层中(这是重点),我必须手动将这些引用链接在一起。
我可以进行某种相对引用,例如render="../outside"
,以跳过对组件父容器的引用吗?
我用 a4j 做了一个 jsf 1 的应用,这个模式到处都在使用。
【问题讨论】:
“这种模式在所有地方都被使用”我的意思是 a4j 似乎会爬上容器层次结构,直到找到匹配项。复合组件 def 似乎在组件边界处终止搜索 【参考方案1】: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>
【讨论】:
【参考方案2】:经过一番修改,这里有一个解决方案:
在事件上放置一个监听器:
<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】:我找到了一个我很满意的更好的解决方案,它利用了模板中的隐式“组件”映射。它允许使用../
文件系统表示法从复合组件返回基本的相对映射。它可以扩展以处理更多,但这就是我所需要的。它也适用于执行参数。
感谢我解决这个问题!再说一次,我是不是误会了什么?我应该不需要弄清楚这一点。
用法:
<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;
errrr - 我不知道为什么我在计算背面时使用StringBuilder
,但你明白了。是这样的。
【讨论】:
【参考方案4】:您可以使用render="@all"
或render="@form"
分别渲染所有内容或整体。
或者,您可以将要更新的内容的绝对 ID 作为参数传递到组件中。这样可以保持灵活性,无需重新渲染过多的页面。
【讨论】:
@all 工作,用 JBoss AS 7.1.0.CR1b 测试。但在大多数情况下它太重了【参考方案5】:在 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。
【讨论】:
以上是关于JSF 2.0 复合组件 - ajax 渲染参数 OUTSIDE 组件定义的主要内容,如果未能解决你的问题,请参考以下文章
JSF 2 - 如何将 Ajax 侦听器方法添加到复合组件接口?
JSF拒绝处理深层嵌套的复合组件。不,真的:“JSF1098:[...]这浪费了处理器时间[...]”