1

您好,我想实现一个 CC 类似的实现选择属性。这类似于 Primefaces 的即时行选择 <p:dataTable selection="#{bean.user}" .../>

这是复合材料中的相关定义:

<composite:interface componentType="my.CcSelection">
  <composite:attribute name="actionListener" required="true"
          method-signature="void listener(javax.faces.event.AjaxBehaviorEvent)"/>
  <composite:attribute name="selection"/>
</composite:interface>

<composite:implementation>
  ...
  <ui:repeat var="item" value="#{cc.attrs.data}">
    <p:commandLink actionListener="#{cc.actionListener(item)}"/>
  </ui:repeat>
  ...
</composite:implementation>

actionListener支持 bean 中的 - 方法如下:

public void actionListener(MyObject object)
{
  logger.info("ActionListener "+object); //Always the correct object
  FacesContext context = FacesContext.getCurrentInstance();

  Iterator<String> it = this.getAttributes().keySet().iterator();
  while(it.hasNext()) {   //Only for debugging ...
    logger.debug(it.next());
  }

  // I want the set the value here
  ValueExpression veSelection = (ValueExpression)getAttributes().get("selection");
  veSelection.setValue(context.getELContext(), object);

  // And then call a method in a `@ManagedBean` (this works fine)  
  MethodExpression al = (MethodExpression) getAttributes().get("actionListener");
  al.invoke(context.getELContext(), new Object[] {});
}

如果我使用带有值表达式的 CC 进行选择(例如selection="#{testBean.user}"veSelectionnull(并且在调试迭代中未打印选择)并且我得到 NPE。如果我传递一个字符串(例如selection="test",属性选择在调试中可用-迭代,但(当然)我得到一个ClassCastException

java.lang.String cannot be cast to javax.el.ValueExpression

如何为我的组件提供actionListenerselection属性,并在第一步中设置选定的值,然后调用actionListener

4

1 回答 1

2

至于调试迭代,您不会在 keyset 或 entryset 中看到值表达式UIComponent#getAttributes()。这也在javadoc中明确提到。换句话说,该映射仅包含具有静态值的条目。只有当你get()在地图上显式调用,并且底层属性是一个值表达式时,它才会真正调用它并返回评估值。

为了获得值表达式,请UIComponent#getValueExpression()改用。

ValueExpression selection = getValueExpression("selection");

至于方法表达式,好吧,如果您的复合从 扩展,那是最简单的UICommand,但在您的特定情况下,这很笨拙。只需将侦听器方法的目标设置为命令链接并用于<f:setPropertyActionListener>在 bean 中设置所需的属性。这样就不需要支持组件了。

<composite:interface>
  <composite:attribute name="actionListener" required="true" targets="link"
          method-signature="void listener(javax.faces.event.AjaxBehaviorEvent)"/>
  <composite:attribute name="selection"/>
</composite:interface>

<composite:implementation>
  ...
  <ui:repeat var="item" value="#{cc.attrs.data}">
    <p:commandLink id="link">
      <f:setPropertyActionListener target="#{cc.attrs.selection}" value="#{item}" />
    </p:commandLink>
  </ui:repeat>
  ...
</composite:implementation>
于 2013-01-27T18:55:51.840 回答