根据JSF<composite:interface>
文档:
复合组件的嵌套
实现必须支持复合组件的嵌套。具体来说,一个复合组件的部分必须可以作为另一个复合组件的使用页面。当复合组件向使用页面公开行为接口时,例如 、 或其他行为接口,在嵌套复合组件的情况下,必须能够“传播”此类接口的公开。复合组件作者必须确保名称属性的值在所有嵌套级别上完全匹配,以使这种公开工作。该实现不需要支持嵌套复合组件中名称的“重新映射”。
它继续展示了一个嵌套的例子,<composite:actionSource>
但是,我一直在测试一个几乎完全一样的例子,但它不起作用。这是我的代码:
内部复合组件:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
xmlns:composite="http://java.sun.com/jsf/composite">
<composite:interface>
<composite:attribute name="actionText"
type="java.lang.String" default="nestedastest action" />
<composite:actionSource name="someaction" />
</composite:interface>
<composite:implementation>
<h:commandLink id="someaction">#{cc.attrs.actionText}</h:commandLink>
</composite:implementation>
</html>
外部复合组件:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
xmlns:composite="http://java.sun.com/jsf/composite"
xmlns:test="http://java.sun.com/jsf/composite/components/test">
<composite:interface name="nestedActionTester"
displayName="A test composite component for nested actions">
<composite:attribute name="actionText"
type="java.lang.String" default="astest action" />
<composite:actionSource name="someaction" />
</composite:interface>
<composite:implementation>
<test:nestedastest actionText="#{cc.attrs.actionText}" />
</composite:implementation>
</html>
小面:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
xmlns:test="http://java.sun.com/jsf/composite/components/test">
<h:head />
<h:body>
<ui:composition template="template.xhtml">
<ui:define name="content">
<h:form id="communityMembersForm">
<div>
<test:astest>
<f:actionListener for="someaction"
binding="#{testController.someActionActionListener}" />
</test:astest>
</div>
<div>
<test:nestedastest>
<f:actionListener for="someaction"
binding="#{testController.someActionActionListener}" />
</test:nestedastest>
</div>
</h:form>
</ui:define>
</ui:composition>
</h:body>
</html>
托管豆:
package test.controller;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ManagedBean
@ViewScoped
public class TestController {
private static Logger logger =
LoggerFactory.getLogger( TestController.class );
public ActionListener getSomeActionActionListener() {
return new ActionListener() {
@Override
public void processAction( ActionEvent event )
throws AbortProcessingException {
logger.debug( "someaction occurred..." );
}
};
}
}
我正在使用 Mojarra 2.1.13:
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.1.13</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.1.13</version>
<type>jar</type>
<scope>runtime</scope>
</dependency>
在 Tomcat 6.0.32 上:
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>el-api</artifactId>
<version>6.0.32</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>servlet-api</artifactId>
<version>6.0.32</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
当我运行这个应用程序时,链接nestedastest action
(它是直接使用内部复合组件的链接)导致动作侦听器运行并打印日志消息。但是,当astest action
单击(外部复合组件)时,没有任何反应。鉴于这几乎正是官方 JSF javadoc 中显示的示例,我希望它能够工作。知道为什么不是吗?
- - - - - 编辑 - - - - -
我发现如果我这样修改外部复合组件:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
xmlns:composite="http://java.sun.com/jsf/composite"
xmlns:test="http://java.sun.com/jsf/composite/components/test">
<composite:interface name="nestedActionTester"
displayName="A test composite component for nested actions">
<composite:attribute name="actionText"
type="java.lang.String" default="astest action" />
<composite:actionSource name="someaction" targets="inner" />
</composite:interface>
<composite:implementation>
<test:nestedastest id="inner" actionText="#{cc.attrs.actionText}" />
</composite:implementation>
</html>
请注意,我向 actionSource 添加了一个 targets 属性,并为嵌套的复合组件添加了一个匹配的 id
它现在将适当地链接操作。这确实有道理,但文档让您相信这是不必要的。这是文档中的错误吗?还是在实现中(我在 Mojarra 2.1.13 和 MyFaces 2.1.10 上都试过了)?还是按照我的理解?