4

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

4

5 回答 5

8

在 JSF 2.0 中,您可以使用EL中的隐式cc和对象。component为了获取任何组件的完整客户端 ID,请执行以下操作:

#{component.clientId}

要检索复合组件的客户端 ID,请执行以下操作:

#{cc.clientId}

同样,您也可以使用#{cc.parent}. 在这种情况下,这可能就是您想要的。有关更长的答案,请参阅使用 JSF 2.0 在命名容器中获取组件 clientId 的完整前缀

于 2010-08-18T08:57:56.990 回答
1

您可以分别使用render="@all"render="@form"渲染所有内容或整体。

或者,您可以将要更新的内容的绝对 id 作为参数传递到组件中。这保持了灵活性,而无需重新渲染过多的页面。

于 2010-06-21T21:53:59.373 回答
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;
}

即便如此,你为什么要这样做?

于 2010-06-22T00:56:49.643 回答
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;
}

errrr - 我不知道为什么我StringBuilder在计算背部时使用了,但你明白了。是这样的。

于 2010-06-22T07:41:23.740 回答
0

cc.parent.cliendId 解析父复合组件而不是直接父组件。 获取JSF2复合组件父级的clientId

<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>               
于 2016-12-08T11:50:10.533 回答