简体   繁体   English

嵌套复合组件中的JSF Composite:actionSource

[英]JSF composite:actionSource in nested composite components

According to the JSF documentation for <composite:interface> : 根据<composite:interface>JSF文档

Nesting of composite components 复合组件的嵌套

The implementation must support nesting of composite components. 该实现必须支持复合组件的嵌套。 Specifically, it must be possible for the section of a composite component to act as the using page for another composite component. 具体而言,复合组件的该部分必须有可能充当另一个复合组件的使用页面。 When a composite component exposes a behavioral interface to the using page, such as a , , or other behavioral interface, it must be possible to “propogate” the exposure of such an interface in the case of a nested composite component. 当复合组件向使用页面公开行为界面,例如,或其他行为界面时,在嵌套复合组件的情况下,必须能够“促进”此类界面的公开。 The composite component author must ensure that the value of the name attributes exactly match at all levels of the nesting to enable this exposure to work. 复合组件作者必须确保name属性的值在嵌套的所有级别上都完全匹配,以使此公开工作正常进行。 The implementation is not required to support “re-mapping” of names in a nested composite component. 不需要实现即可支持嵌套复合组件中名称的“重新映射”。

It goes on to show an example of nesting <composite:actionSource> however, I have been testing an example almost exactly like that and it doesn't work. 它继续显示嵌套<composite:actionSource>的示例,但是,我一直在测试几乎完全像这样的示例,但是它不起作用。 Here is my code: 这是我的代码:

Inner Composite Component: 内部复合成分:

<!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>

Outer Composite Component: 外复合组件:

<!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>

Facelet: 小面:

<!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>

Managed Bean: 托管Bean:

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..." );
            }

        };
    }
}

I am using Mojarra 2.1.13: 我正在使用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>

On tomcat 6.0.32: 在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>

When I run this application, the link for nestedastest action (which is the link that uses the inner composite component directly) causes the action listener to run and the log message to print. 当我运行此应用程序时, nestedastest action的链接(直接使用内部复合组件的链接)将导致操作侦听器运行并记录日志消息。 However, when the astest action (the outer composite component) is clicked nothing happens. 但是,单击astest action (外部复合组件)时,什么也不会发生。 Given that this is almost exactly the example shown in the official JSF javadoc, I would expect this to work. 鉴于这几乎与官方JSF javadoc中显示的示例完全一样,因此我希望它可以正常工作。 Any idea why it isn't? 知道为什么不是吗?

---------- EDIT --------- ----------编辑---------

I have found that if I modify the outer composite component thusly: 我发现如果我这样修改外部复合组件:

<!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>

Note that I added a targets attribute to the actionSource and a matching id to the nested composite component 请注意,我将target属性添加到actionSource,并将匹配的ID添加到嵌套的复合组件

It will now chain the action appropriately. 现在它将适当地链接操作。 This does make sense, but the documentation leads you to believe this is unnecessary. 这确实是有道理的,但是文档使您相信这是不必要的。 Is this an error in the documentation? 这是文档中的错误吗? Or in the implementation (I tried it out both on Mojarra 2.1.13 and MyFaces 2.1.10)? 还是在实现中(我在Mojarra 2.1.13和MyFaces 2.1.10上都尝试过)? Or in my understanding? 还是我的理解?

The algorithm try to find by default a component with the same id as the one defined by cc:actionSource name in each nested level. 该算法默认尝试在每个嵌套级别中找到与cc:actionSource名称定义的组件具有相同ID的组件。 In this case, the component id is only defined on the inner level. 在这种情况下,组件ID仅在内部级别定义。 If you don't want to use the same id for each component all the way down, you can use "targets" attribute to indicate the algorithm which component is talking about, and pass the actionListener by all the levels. 如果不想一直对每个组件使用相同的ID,则可以使用“ targets”属性指示正在讨论哪个组件的算法,并在所有级别传递actionListener。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM