【问题标题】:JSF2.0 - Composite component with optional method expressionJSF2.0 - 具有可选方法表达式的复合组件
【发布时间】:2013-03-03 10:33:41
【问题描述】:

我正在实现一个复合组件,但我发现了一个我没有找到解决方案的问题。

我指定了页面作者可以或不可以传递的属性,但是我无法指定方法属性(Action 的方法表达式),如果未传递,则复合组件不会使用Composite:implementation 标签中的方法属性。

这是我的代码:

<composite:interface>
    <composite:attribute name="namePrompt" required="true"/>
    <composite:attribute name="actionMethod" method-signature="java.lang.String  action()" required="false"/>
    <composite:attribute name="showComponent" default="false"/>
</composite:interface>

<composite:implementation>
    <div>
       <p:commandLink actionListener="#{cc.attrs.actionMethod}"
                      rendered="#{cc.attrs.showComponent}"
                      >
            <h:outputText value="#{cc.attrs.namePrompt}"/>    
       </p:commandLink>
    </div>
</composite:implementation>

在使用的时候,我没有指定“actionMethod”属性。像这样:

<util:foo namePrompt="SomeName" showComponent="true"/>

但我收到错误消息:

javax.faces.FacesException: Unable to resolve composite component from using page using EL expression '#{cc.attrs.actionMethod}'

有没有办法做到这一点?

【问题讨论】:

  • 您可以将可选属性传递给actionListener。你是什​​么用例,当actionListener 没有被解析并且commandLink 被渲染时,你认为应该发生什么?
  • 是的,链接组件已呈现,但是当链接组件中发生单击操作时,它抱怨我没有为属性 actionMethod 定义方法。但这是我的意图,有时我不想为 actionMethod 属性定义一个动作方法。这可能吗?我认为把'required = false'解决问题。

标签: jsf-2 java-ee-6 composite-component


【解决方案1】:

您必须创建两个p:commandLink 元素并根据参数定义有条件地渲染它们:

<p:commandLink actionListener="#{cc.attrs.actionMethod}" rendered="#{!empty cc.getValueExpression('actionMethod') and cc.attrs.showComponent}">
  <h:outputText value="#{cc.attrs.namePrompt}"/>
</p:commandLink>
<p:commandLink rendered="#{empty cc.getValueExpression('actionMethod')}">
  <h:outputText value="#{cc.attrs.namePrompt}"/>
</p:commandLink>

【讨论】:

    【解决方案2】:

    将方法签名返回类型更改为java.lang.Object,并添加“null”作为默认值。

    <composite:interface>
        <composite:attribute name="namePrompt" required="true"/>
        <composite:attribute name="actionMethod" method-signature="java.lang.Object action()" required="false" default="null"/>
        <composite:attribute name="showComponent" default="false"/>
    </composite:interface>
    
    <composite:implementation>
        <div>
           <p:commandLink actionListener="#{cc.attrs.actionMethod}"
                          rendered="#{cc.attrs.showComponent}"
                          >
                <h:outputText value="#{cc.attrs.namePrompt}"/>    
           </p:commandLink>
        </div>
    </composite:implementation>
    

    没有方法:

    <util:foo namePrompt="SomeName" showComponent="true"/>
    

    使用方法:

    <util:foo actionMethod="#{someBean.someMethod()}" namePrompt="SomeName" showComponent="true"/>
    

    【讨论】:

      【解决方案3】:

      另一种解决方案是使用操作方法创建自己的组件类型。示例:

      <composite:interface componentType="myButton">
          <composite:attribute name="namePrompt" required="true"/>
          <composite:attribute name="actionMethod" method-signature="java.lang.String  action()" required="false"/>
          <composite:attribute name="showComponent" default="false"/>
      </composite:interface>
      
      <composite:implementation>
          <div>
             <p:commandLink actionListener="#{cc.action()}" rendered="#{cc.attrs.showComponent}">
                <h:outputText value="#{cc.attrs.namePrompt}"/>    
            </p:commandLink>
         </div>
      </composite:implementation>
      

      并且组件类型必须看起来像:

      @FacesComponent("myButton")
      public class MyButton extends UINamingContainer {
      
          public MyButton () {
          }
      
          public String action() {
              MethodExpression me = (MethodExpression) this.getAttributes().get("actionMethod");
              if (me != null) {
                  try {
                      Object result = me.invoke(FacesContext.getCurrentInstance().getELContext(),     null);
                      if (result instanceof String) {
                          return (String) result;
                      }
                  } catch (ValidatorException ve) {
                      throw ve;
                  }
              }
              return null;
          }
      }
      

      【讨论】:

        【解决方案4】:

        有同样的错误,我的组件也需要一个可选的操作方法。

        所以我尝试使用方法签名在复合属性上添加一个默认参数,指向相应 FacesComponent 类上的方法,效果很好!

        组件:

        <composite:interface componentType="myButton">
            <composite:attribute name="namePrompt" required="true"/>
            <composite:attribute name="actionMethod" method-signature="java.lang.String  action()" required="false" default="#{cc.dummyAction}"/>
            <composite:attribute name="showComponent" default="false"/>
        </composite:interface>
        
        <composite:implementation>
            <div>
               <p:commandLink action="#{cc.attrs.actionMethod}"
                              rendered="#{cc.attrs.showComponent}"
                              >
                    <h:outputText value="#{cc.attrs.namePrompt}"/>    
               </p:commandLink>
            </div>
        </composite:implementation>
        

        FacesComponent 类:

        @FacesComponent("myButton")
        public class MyButton extends UINamingContainer {
        
            public MyButton () {
            }
        
            public String dummyAction() {
               return "";
            }
        
        }
        

        【讨论】:

          【解决方案5】:

          避免将方法放在复合材料中。如果您需要这样做,请将具有该方法的类放在组合中,并像这样使用它:

          <composite:interface>
             <composite:attribute name="classWithMethod" 
                                  method-signature="java.lang.String"/>
          </composite:interface>
          

          以及实现:

          <composite:implementation>
             <div>
                <p:commandLink 
                   actionListener="#{cc.attrs.classWithMethod.actionMethod}">    
                </p:commandLink>
             </div>
          </composite:implementation>
          

          为我工作! :D

          【讨论】:

            猜你喜欢
            • 2023-04-01
            • 1970-01-01
            • 2023-03-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-05-15
            • 1970-01-01
            相关资源
            最近更新 更多