如何在复合组件中将嵌套在ui:repeat内的commandLink作为目标?

时间:2013-08-20 20:52:46

标签: jsf jsf-2 composite-component

我正在尝试创建一个paginator复合组件。该组件应为每个可用页面呈现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"/>

1 个答案:

答案 0 :(得分:2)

您应该删除<cc:interface>中的操作属性。因为您通过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>