无法让MenuItem调用其ActionListener

时间:2012-02-10 02:37:29

标签: jsf jsf-2 primefaces actionlistener

我试图让MenuItem [在Menubar内]发出ActionEvent并在按下时调用方法,但是,从不调用监听方法,而我不明白为什么:

xhtml页面:

<h:body>
<h:form>
    <p:menubar model="#{testBean.model}" />
    <h:commandButton value="submit" />
    <h:outputText value="#{testBean.confirmation}" />
</h:form>
</h:body>
</html>

jsf bean:

@ManagedBean
public class TestBean implements ActionListener{

    MenuModel model = new DefaultMenuModel();
    private String confirmation = "negative";

    public TestBean() {
        MenuItem item = new MenuItem();
        item.setValue("Click");
        item.setUrl("#");
        item.addActionListener(this);
        model.addMenuItem(item);
    }

    @Override
    public void processAction(ActionEvent event)
            throws AbortProcessingException {

        // EXECUTION NEVER REACHES HERE!
        confirmation = "positive";
    }

    public MenuModel getModel() {
        return model;
    }

    public String getConfirmation() {
        return confirmation;
    }
}

可视化非常简单的输出可能有所帮助:

enter image description here

我正在使用Primefaces 3.1.0和JSF 2.0

4 个答案:

答案 0 :(得分:3)

我的第一个建议是向你的动作监听器添加某种调试日志记录,以便找出它是否被调用。如果它被调用但您的网站没有呈现更改,则可能是由于以下原因。

  • 动作侦听器不会触发客户端DOM的更新。
  • 提交按钮会触发请求。托管bean被提升并使用默认值重新初始化,因为它在请求范围内进行管理。您应该尝试将bean放入@ViewScoped@SessionScoped管理中。

顺便说一下,我们没有实施ActionListener。我们将方法表达式分配给菜单项。这是一个简短的模型示例:我们使用菜单项的操作来切换上下文菜单的按钮状态。希望我能以某种方式帮助你。

Facelet代码段:

<p:menu model="#{menuBean.model}" />

Bean片段:

@ManagedBean
@ViewScoped
public class MenuBean implements Serializable {

    private MenuModel model;
    private boolean cutAllowed = false;

    /** Creates a new instance of MenuBean */
    public MenuBean() {
        model = new DefaultMenuModel();

        //First submenu
        Submenu submenu = new Submenu();
        submenu.setLabel("Dynamic Submenu 1");

        MenuItem item = new MenuItem();
        item.setValue("toggle");
        item.setUpdate("contextMenu");
        item.setAjax(true);
        item.setIcon("ui-icon ui-icon-disk");
        ExpressionFactory factory = FacesContext.getCurrentInstance().getApplication().getExpressionFactory();
        MethodExpression methodExpression = factory.createMethodExpression(FacesContext.getCurrentInstance().getELContext(), "#{menuBean.toggleCutState}", String.class, new Class[]{});

        item.setActionExpression(methodExpression);

        submenu.getChildren().add(item);

        model.addSubmenu(submenu);
    }

    public boolean isCutAllowed() {
        return cutAllowed;
    }

    public void setCutAllowed(boolean cutAllowed) {
        this.cutAllowed = cutAllowed;
    }

    public String toggleCutState() {
        toggleCutState(null);
        return null;
    }

    public void toggleCutState(ActionEvent event) {
        this.cutAllowed = !this.cutAllowed;
        System.out.println("toggle called");
    }       

    public MenuModel getModel() {
        return model;
    }  
}

答案 1 :(得分:1)

原始代码的第一个问题是我需要一个唯一的ID。我很早就发现了这一点,但它导致了另一个非常恼人的问题:将调用动作侦听器,但页面不会更新。要解决此问题(如here所述),您可以在MenuItem上禁用ajax或自定义更新方式。

正确的构造函数代码是:

public TestBean() {
    MenuItem item = new MenuItem();
    item.setValue("Click");

    // New code:
    item.setId(FacesContext.getCurrentInstance().getViewRoot().createUniqueId());
    item.setAjax(false);

    item.setUrl("#");
    item.addActionListener(this);
    model.addMenuItem(item);
}

答案 2 :(得分:1)

@Mogwli,item.setId((new UiViewRoot())。createUniqueId());因为新的UIViewRoot()不能识别上下文,所以会导致IllegalArgumentException ...应该是item.setId(FacesContext.getCurrentInstance()。getViewRoot()。createUniqueId());

答案 3 :(得分:0)

首先,您的代码段显示<h:commandButton> Primefaces commandButton <p:commandButton>

其次,您没有指定commandButton的actionListener属性指向processAction

<p:commandButton value="submit" actionListener="#{testBean.processAction}" />