Reputation: 4128
I am trying to get a Primefaces MenuItem
[within a Menubar
] to emit an ActionEvent
and call a method when pressed, however, the listening methods are never called, and I have no idea why:
xhtml page:
<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;
}
}
It might help to visualise the very simple output:
I'm using Primefaces 3.1.0, and JSF 2.0
Upvotes: 2
Views: 8938
Reputation: 4128
The first problem with the original code was that I needed a unique Id. I discovered this early on, but it lead to another very annoying issues: the action listener would be called, but the page would not update. To solve this issue (as described here), you either disable ajax on the MenuItem or customise how it updates.
The correct constructor code is:
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);
}
Upvotes: 1
Reputation: 19
@Mogwli, item.setId((new UiViewRoot()).createUniqueId()); will cause an IllegalArgumentException since new UIViewRoot() will not be context aware... Should have been item.setId(FacesContext.getCurrentInstance().getViewRoot().createUniqueId());
Upvotes: 1
Reputation: 10463
First of all, your code snippet shows an <h:commandButton>
which is not the Primefaces commandButton <p:commandButton>
.
Secondly, you are not specifying the actionListener
attribute of the commandButton to point to processAction
.
<p:commandButton value="submit" actionListener="#{testBean.processAction}" />
Upvotes: 0
Reputation: 2099
My first suggestion is to add some kind of debug logging to your action listener in order to find out, whether it got called or not. If it gets called but your site isn't rendering the changes it might be due to the following reasons.
@ViewScoped
or @SessionScoped
management. By the way, we do not implement ActionListener
. We assign method expressions to the menu items. Here is a short mockup example: We used an action of a menu item to toggle button states of a context menu. Hope I could help you somehow.
Facelet snippet:
<p:menu model="#{menuBean.model}" />
Bean snippet:
@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;
}
}
Upvotes: 3