0

根据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 上都试过了)?还是按照我的理解?

4

1 回答 1

0

默认情况下,该算法尝试在每个嵌套级别中查找与 cc:actionSource 名称定义的组件具有相同 id 的组件。在这种情况下,组件 id 仅在内部级别上定义。如果您不想一直使用相同的 id 为每个组件,您可以使用“targets”属性指示哪个组件正在谈论的算法,并通过所有级别传递 actionListener。

于 2012-12-05T00:01:21.337 回答