【问题标题】:How to target a commandLink nested inside an ui:repeat, in a composite component?如何在复合组件中定位嵌套在 ui:repeat 中的 commandLink?
【发布时间】:2013-08-23 01:52:10
【问题描述】:

我正在尝试创建一个分页器复合组件。该组件应为每个可用页面呈现一个 commandLink。它看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:cc="http://java.sun.com/jsf/composite"
      xmlns:ui="http://java.sun.com/jsf/facelets">
    <cc:interface>
        <cc:attribute name="action" targets="jumpButton" required="true"/>
        <cc:attribute name="bean" type="java.lang.Object" required="true"/>
    </cc:interface>
    <cc:implementation>
        <ui:repeat value="#{cc.attrs.bean.pages}" var="page">
            <h:commandLink id="jumpButton"
                           actionListener="#{cc.attrs.bean.jumpToPage(page)}">
                <h:outputText value="#{page}"/>
            </h:commandLink>
        </ui:repeat>
    </cc:implementation>
</html>

该组件用于各种页面,如下所示:

<ccc:paginator bean="#{myBean}"
               action="/index?faces-redirect=true&amp;includeViewParams=true"/>

或者:

<ccc:paginator bean="#{myOtherBean}"
               action="/dir/index?faces-redirect=true&amp;includeViewParams=true"/>

注意 faces-redirect=true 和 includeViewParams=true 的使用,据我所知不能直接在复合组件中的 commandLinks 上使用。

问题是 jumpButton 不能成为目标,因为它在 ui:repeat 中。我收到消息:

javax.servlet.ServletException: /index?faces-redirect=true&includeViewParams=true : Unable to re-target MethodExpression as inner component referenced by target id 'jumpButton' cannot be found.

如果我在 ui:repeat 之外创建 id="jumpButton" 的命令链接,则复合组件和按钮可以正常工作。如何使我的复合组件与 ui:repeat 中的命令链接一起使用?

解决方案

托管 bean 的 jumpToPage 动作:

public String jumpToPage(String path, Integer page) {
    ...
    setCurrentPage(page);
    return path;
}

复合组件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:cc="http://java.sun.com/jsf/composite"
      xmlns:ui="http://java.sun.com/jsf/facelets">
    <cc:interface>
        <cc:attribute name="bean" type="java.lang.Object" required="true"/>
        <cc:attribute name="path" type="java.lang.String" required="true"/>
    </cc:interface>
    <cc:implementation>
        <ui:repeat value="#{cc.attrs.bean.pages}" var="page">
            <h:commandLink id="jumpButton"
                           action="#{cc.attrs.bean.jumpToPage(cc.attrs.path, page)}">
                <h:outputText value="#{page}"/>
            </h:commandLink>
        </ui:repeat>
    </cc:implementation>
</html>

组件使用示例:

<ccc:paginator bean="#{myBean}"
               path="/index?faces-redirect=true&amp;includeViewParams=true"/>
<ccc:paginator bean="#{myOtherBean}"
               path="/dir/index?faces-redirect=true&amp;includeViewParams=true"/>

【问题讨论】:

    标签: jsf jsf-2 composite-component


    【解决方案1】:

    您应该删除&lt;cc:interface&gt; 中的操作属性。不需要,因为您通过 bean 属性调用操作。

    更新 1

    您还可以将操作的结果定义为 bean 的返回值。像这样:

    public class MyBean {
        public String jumpToPage(int page){
           // ...
           return "/index?faces-redirect=true&amp;includeViewParams=true";
        }
    }
    

    然后用action代替actionListener

     <h:commandLink id="jumpButton" action="#{cc.attrs.bean.jumpToPage(page)}">
         <h:outputText value="#{page}"/>
     </h:commandLink>
    

    【讨论】:

    • 谢谢,我对原来的问题做了一些修改。据我所知,我不可能直接在复合组件中的 commandLinks 上使用?faces-redirect=true&amp;includeViewParams=true。如果不是这样,您的建议将有效。但是分页器的?faces-redirect=true&amp;includeViewParams=true 部分很重要。
    • 查看我的更新。您仍然不需要组件上的 action 属性。
    • 谢谢!很简单。不敢相信我把它弄得这么复杂。我已经用结果更新了我的问题。效果很好。
    猜你喜欢
    • 1970-01-01
    • 2012-11-07
    • 2010-12-28
    • 1970-01-01
    • 2012-11-18
    • 2020-03-21
    • 1970-01-01
    • 2012-07-11
    • 1970-01-01
    相关资源
    最近更新 更多