【问题标题】:JSF: How to attach an actionListener to component created programatically?JSF:如何将 actionListener 附加到以编程方式创建的组件?
【发布时间】:2010-01-27 14:52:28
【问题描述】:

我必须动态创建一些 commandLinks 并为其附加一些动作侦听器,因此我将 <h:panelGrid> 放在 JSP 页面上并使用此类代码添加 commandLinks 并将动作侦听器分配给:

public ManagedBean(){
 List<UIComponenet> child = panelGrid.getChilderen();
 list.clear();

 List<MyClass> myList = getSomeList();

 for (MyClass myObj : myList){
   FacesContext ctx = FacesContext.getCurrentContext();
   HtmlCommandLink cmdLink = (HtmlCommandLink) ctx.getApplication.createComponent(HtmlCommandLink.COMPONENT_TYPE);
   cmdLink.setValue(myObj.getName());
   cmdLink.setActionLinstner(new ActionListener(){
     public void processAction(ActionEvent event) throws AbortProcessingException{
       System.out.println (">>>>>>>>>>>>>>>>>I am HERE ");
     }
   });
   child.add(cmdLink);
 }
}

但不幸的是,当我按下这个commandLinks 时,抛出了一个异常!如何在运行时添加组件事件监听器?

(注意,我上面的代码包含我刚刚写的语法/编译错误)。

【问题讨论】:

  • 目前没有堆栈跟踪,但它应该可以工作吗?

标签: jsf


【解决方案1】:

首先,您需要手动为任何动态创建的UINamingContainerUIInputUICommand 组件分配ID。否则 JSF 无法根据请求参数在组件树中找到它们,因为它与自动生成的 ID 不匹配。

因此,至少这样做:

HtmlCommandLink link = new HtmlCommandLink();
link.setId("linkId");
// ...

其次,您应该创建一个ActionListenerMethodExpression,如下所示:

FacesContext context = FacesContext.getCurrentInstance();
MethodExpression methodExpression = context.getApplication().getExpressionFactory().createMethodExpression(
    context.getELContext(), "#{bean.actionListener}", null, new Class[] { ActionEvent.class });

link.addActionListener(new MethodExpressionActionListener(methodExpression));
// ...

...当然在#{bean}后面的backing bean类中有如下方法:

public void actionListener(ActionEvent event) {
    // ...
}

以上所有动态内容基本上与以下原始 JSF 标记相同:

<h:commandLink id="linkId" actionListener="#{bean.actionListener}" />

【讨论】:

  • 干得好,非常感谢:) 但我注意到,第一次点击任何命令链接都不起作用,只有从第二次点击监听器开始调用。
  • 给所有父UINamingContainer(例如UIFormUIData等)元素一个固定 ID(动态或静态)并且不 使用 MyFaces/Tomahawk 的 prependId="false" -- 如果有的话。
  • @BalusC 如果我有一个 UIComponent button = viewRoot.findComponent("save"); ?我该如何添加 actionListener 呢?我还使用 MethodExpression 吗?它问我必须强制转换为 UICommand 但我收到错误
【解决方案2】:

我遇到了同样的问题。 瞬态组件不适用于 actionListener。 不要打电话

FacesContext.getCurrentInstance().getViewRoot().setTransient(true); 或者 component.setTransient(true);

我一删除就没事了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多