0

我将解释在模板中使用一个复合组件时遇到的问题。

想象一个像这样的视图,它与具有视图范围的通用托管 bean 一起工作。我将它作为参数传递给模板。

<?xml version='1.0' encoding='UTF-8' ?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"  
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:c="http://java.sun.com/jsp/jstl/core"
  xmlns:trkal="http://java.sun.com/jsf/composite/trkalcomponents">

  <ui:composition template="/template.xhtml">
      <ui:param name="maisuBean" value="#{genericBean}" />
  </ui:composition>
</html>

模板是这样的。除了其他组件,它还使用一个复合组件。

<?xml version='1.0' encoding='UTF-8' ?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"  
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:trkal="http://java.sun.com/jsf/composite/trkalcomponents">

<h:head>
    <title>Titulo</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</h:head>

<h:body>
    <h:form enctype="multipart/form-data">
        ...
        <trkal:toolbarbuttonwidget id="buttonToolbar" label="Action" iconName="toolbar.png"
            buttonAction="#{maisuBean.myActionListener}"
            >
        </trkal:toolbarbuttonwidget>
        ...
        <h:commandLink id="otherButton" actionListener="#{maisuBean.myActionListener}">
            <h:graphicImage library="images" name="toolbar.png" />
            <h:outputText value="Other Action" />
        </h:commandLink>
        ...

    </h:form>
</h:body>
</html> 

如您所见,此模板使用一个复合组件,允许指定听到此事件的动作侦听器。

<composite:interface>
    <composite:attribute name="id" />
    <composite:attribute name="buttonAction" method-signature="void myAction(javax.faces.event.ActionEvent)" targetAttributeName="actionListener"/>
    <composite:attribute name="iconName" />
    <composite:attribute name="label"/>
    <composite:attribute name="title"/>
    <composite:attribute name="styleClass"/>
</composite:interface>
<composite:implementation>
    <h:outputStylesheet target="head" library="trkalcomponents" name="toolbarbuttonwidget.css"  />
    <h:commandLink id="buttonAction">
        <h:graphicImage library="images" name="#{cc.attrs.iconName}" />
        <h:outputText value="#{cc.attrs.label}" />
    </h:commandLink>
</composite:implementation>

如果我点击otherButton,它工作正常,但如果我点击buttonToolbar它不工作。

09-nov-2012 19:16:28 javax.faces.event.MethodExpressionActionListener processAction
GRAVE: Se ha recibido 'javax.el.PropertyNotFoundException' al invocar la escucha de acción '#{maisuBean.myActionListener}' para el componente 'buttonAction'
09-nov-2012 19:16:28 javax.faces.event.MethodExpressionActionListener processAction
GRAVE: javax.el.PropertyNotFoundException: /template.xhtml @20,6 buttonAction="#{maisuBean.myActionListener}": Propiedad 'myActionListener' no hallada en el tipo com.joxeja.test.ToolBarBean
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:111)

它似乎无法解析复合组件内的 EL 表达式。

怎么了?如何在一个模板中使用一个复合组件?

我正在使用 Mojarra 2.1.7

谢谢。

4

1 回答 1

1

对不起,我在第一次阅读时错过了这个:

您的实现未正确定位属性。我犯了这个错误(我很确定我们所有人都这样做)。您需要将属性引用为 ->#{cc.attrs.someAttribute}而不是其名称。您对大多数元素执行此操作,但不是actionListener. 如果那是您的代码,它应该修复它。你的签名是正确的。您正在尝试使用targetAttributeName我不熟悉的。我的猜测是您需要将id组件的名称设置为该名称(因此您的按钮myAction不会actionListener(如果我引用的示例与您相同)。

除此之外,我会怎么做:

    <composite:interface>
    <composite:attribute name="id" />
    <!-- 
    <composite:attribute name="buttonAction" method-signature="void myAction(javax.faces.event.ActionEvent)" targetAttributeName="actionListener"/>
    -->
    <composite:attribute name="buttonAction" method-signature="void action(javax.faces.event.ActionEvent)"/>  
    <composite:attribute name="iconName" />
    <composite:attribute name="label"/>
    <composite:attribute name="title"/>
    <composite:attribute name="styleClass"/>
</composite:interface>
<composite:implementation>
    <h:outputStylesheet target="head" library="trkalcomponents" name="toolbarbuttonwidget.css"  />
        <!-- fix below -->
        <h:commandLink id="buttonAction" actionListener=#{cc.attrs.buttonAction}>
            <h:graphicImage library="images" name="#{cc.attrs.iconName}" />
            <h:outputText value="#{cc.attrs.label}" />
        </h:commandLink>
    </composite:implementation>

我喜欢这种方法,因为它与标记页面的其他方式相似,而且看起来很简单。试一试。

于 2012-11-12T15:05:29.327 回答