JSF 2.0 Composite组件 - ajax呈现参数OUTSIDE组件定义

时间:2010-06-21 08:14:43

标签: java jsf-2

考虑一个简单的复合组件,它采用某种动作参数 - 例如,一个简单的链接'美化'。我想'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应用程序,这个模式在整个地方都被使用了。

5 个答案:

答案 0 :(得分:7)

在JSF 2.0中,您可以在EL中使用隐式cccomponent对象。要获取任何组件的完整客户端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>