Programmatic menus offer a more flexible way in comparison with the declarative approach. The whole menu structure can be created in Java and bound as a model to the p:menu
tag. Programmatic menu creation is the best choice when we load a menu definition from a database or XML file, and if the menu structure is not known beforehand.
In this recipe, we will learn about the PrimeFaces menu model and create a programmatic menu.
Every programmatically created menu instance should implement the org.primefaces.model.MenuModel
Java interface. PrimeFaces provides a default implementation, org.primefaces.model.DefaultMenuModel
, that is sufficient to use in most cases. Your own customized implementations of MenuModel
are possible as well. Let's create a static menu from the Statically and dynamically positioned menus recipe in a programmatic way:
@Named @ViewScoped public class ProgrammaticMenuBean implements Serializable { private MenuModel model; @PostConstruct protected void initialize() { model = new DefaultMenuModel(); // first submenu DefaultSubMenu submenu = new DefaultSubMenu(); submenu.setLabel("JavaScript Libraries"); // menu items DefaultMenuItem item = new DefaultMenuItem(); item.setValue("jQuery"); item.setUrl("http://jquery.com"); submenu.addElement(item); item = new DefaultMenuItem(); item.setValue("Yahoo UI"); item.setUrl("http://yuilibrary.com"); submenu.addElement(item); item = new DefaultMenuItem(); item.setValue("Prototype"); item.setUrl("http://prototypejs.org"); submenu.addElement(item); model.addElement(submenu); // second submenu submenu = new DefaultSubMenu(); submenu.setLabel("Operations"); // menu items item = new DefaultMenuItem(); item.setValue("Save"); item.setCommand("#{positionedMenuBean.save}"); item.setUpdate("growl"); submenu.addElement(item); item = new DefaultMenuItem(); item.setValue("Update"); item.setCommand("#{positionedMenuBean.update}"); item.setUpdate("growl"); submenu.addElement(item); item = new DefaultMenuItem(); item.setValue("Delete"); item.setCommand("#{positionedMenuBean.delete}"); item.setUpdate("growl"); submenu.addElement(item); model.addElement(submenu); } public MenuModel getModel() { return model; } }
The created menu can easily be bound to the corresponding component tag by means of the model
attribute:
<p:menu model="#{programmaticMenuBean.model}"/>
After an instance of the DefaultMenuModel
class is created, we create the Submenu
and MenuItem
instances using new DefaultSubMenu()
and new DefaultMenuItem()
, respectively. The MenuItem
instances are children of Submenu
and should be added as submenu.addElement(item)
. Submenu
itself is added to the model as model.addElement(submenu)
. URLs are set by item.setUrl()
as String
objects. The methods to be invoked are set by item.setCommand()
as String
representations of EL expressions.
If you need to pass parameters in AJAX or non-AJAX commands, use the setParam(key, value)
method. Parameters can be extracted again from DefaultMenuItem
in the invoked methods. DefaultMenuItem
is a property of MenuActionEvent
. A code sample for a bean named ParametrizedCommandBean
exemplifies this:
@PostConstruct protected void initialize() { model = new DefaultMenuModel(); DefaultMenuItem item = new DefaultMenuItem(); item.setValue("Command with parameters"); item.setCommand("#{parametrizedCommandBean.command}"); item.setUpdate("growl"); item.setIcon("ui-icon-play"); item.setParam("book", "PrimeFaces Cookbook"); item.setParam("edition", "Second Edition"); model.addElement(item); } public void command(MenuActionEvent event) { DefaultMenuItem item = (DefaultMenuItem) event.getMenuItem(); Map<String, List<String>> params = item.getParams(); FacesMessage msg = new FacesMessage( FacesMessage.SEVERITY_INFO, params.get("book").get(0) + ", " + params.get("edition").get(0), null); FacesContext.getCurrentInstance().addMessage(null, msg); }
The XHTML snippet is easy and is given here:
<p:menu model="#{parametrizedCommandBean.model}" style="width:200px"/>
The preceding XHTML code results in the following output:
This recipe is available in the demo web application on GitHub (https://github.com/ova2/primefaces-cookbook/tree/second-edition). Clone the project if you have not done it yet, explore the project structure, and build and deploy the WAR file on application servers compatible with Servlet 3.x, such as JBoss WildFly and Apache TomEE.
The showcase for the recipe is available at http://localhost:8080/pf-cookbook/views/chapter6/programmaticMenu.jsf
.