JSF2:action和actionListener

时间:2011-12-30 19:27:16

标签: jsf jsf-2 primefaces action actionlistener

BalusC在此回答Differences between action and actionListenerUse actionListener if you want have a hook before the real business action get executed, e.g. to log it, and/or to set an additional property (by <f:setPropertyActionListener>,。但是,当我决定编写一些代码来测试它时,结果有点不同。这是我的小代码

<h:form id="form"> 
   <h:panelGroup id="mygroup">
     <p:dataTable id="mytable" value="#{viewBean.foodList}" var="item">
         <p:column>
             #{item}
         </p:column>
         <p:column>
             <p:commandButton value="delete" 
                        action="#{viewBean.delete}"
                        update=":form:mygroup">
                 <f:setPropertyActionListener target="#{viewBean.selectedFood}"
                                              value="#{item}"/>
             </p:commandButton>
         </p:column>
      </p:dataTable>
   </h:panelGroup>
</h:form>

这是我的豆子

@ManagedBean
@ViewScoped
public class ViewBean {
    private List<String> foodList;
    private String selectedFood;

    @PostConstruct
    public void init(){

        foodList = new ArrayList<String>();
        foodList.add("Pizza");
        foodList.add("Pasta");
        foodList.add("Hamburger");
    }

    public void delete(){
        foodList.remove(selectedFood);
    }
    //setter, getter...
}

根据BalusC,actionListener 更合适,但我的示例显示否则

上面的代码适用于action,但如果我切换到actionListener,那么它就不能正常工作了。我需要两次点击才能使用actionListener删除此表的条目,而如果我使用action,则每次单击按钮时都会删除条目。我想知道那里的任何JSF专家是否可以帮助我理解action vs actionListener

注意如果我切换到actionListener,我的delete方法会变为public void delete(ActionEvent actionEvent)

2 个答案:

答案 0 :(得分:16)

您将actionactionListener混淆。 actionListener始终在action之前运行。如果有多个动作侦听器,则它们的运行顺序与它们已注册的顺序相同。这就是当您使用actionListener调用业务操作并<f:setPropertyActionListener>设置(准备)业务操作要使用的属性时,它无法按预期工作的原因。您在上一个问题Is this Primefaces bug or Mojarra/MyFaces bug中指出并修复了此问题。

delete()方法中的任何内容显然都是商业行为,应由action调用。业务操作通常调用EJB服务,并在必要时还设置最终结果和/或导航到不同的视图。

答案 1 :(得分:4)

我用原始JSF的标签<h:commandButton>尝试了你的例子,但我也得到了相同的症状。我相信如果您指定actionListener属性并同时使用<f:setPropertyActionListener>声明另一个侦听器,则属性actionListener中的侦听器将在另一个之前触发。

更新:我使用以下代码测试我的假设:

  • 将您的delete功能更改为此功能:

    public void delete(){
        this.selectedFood = "Chicken";
        //foodList.remove(selectedFood);
    }
    
  • <h:outputText id="food" value="#{viewBean.selectedFood}" />内添加<h:panelGroup id="mygroup">

您将看到outputText始终为Chicken