MenuModel API is used to create PrimeFaces menu components like menu, tieredMenu, menubar programmatically. This is a very useful feature since in many cases application menus are not static and vary depending on user roles.
Current MenuModel implementation is however is not a real model unlike other PrimeFaces Models and can be considered as a workaround. It uses UIComponent instances directly and manipulates JSF Component Tree directly whereas a proper model should be composed of POJOs and the component should render the UI based on the POJOs. Current implementation also has a couple of limitations, most famous one is the “Cannot remove the same component twice” error because you can only use MenuModel with request scoped beans, otherwise it is likely to receive this error.
For 4.0, we have reimplemented MenuModel from scratch using best practices and it is significantly improved regarding usability, performance and memory usage. Highlights of the new MenuModel are;
- Lightweight
- Based on simple pojos
- Easy to extend
- Easy to persist in a data storage
- Can be used with any scope
Here is a sample implementation;
<p:menu model="#{menuBean.model}" />
public class MenuBean {
private MenuModel model;
public MenuBean() {
model = new DefaultMenuModel();
//First submenu
DefaultSubMenu firstSubmenu = new DefaultSubMenu("Dynamic Submenu");
DefaultMenuItem item = new DefaultMenuItem("External");
item.setUrl("http://www.primefaces.org");
item.setIcon("ui-icon-home");
firstSubmenu.addElement(item);
model.addElement(firstSubmenu);
//Second submenu
DefaultSubMenu secondSubmenu = new DefaultSubMenu("Dynamic Actions");
item = new DefaultMenuItem("Save");
item.setIcon("ui-icon-disk");
item.setCommand("#{menuBean.save}");
item.setUpdate("messages");
secondSubmenu.addElement(item);
item = new DefaultMenuItem("Delete");
item.setIcon("ui-icon-close");
item.setCommand("#{menuBean.delete}");
item.setAjax(false);
secondSubmenu.addElement(item);
item = new DefaultMenuItem("Redirect");
item.setIcon("ui-icon-search");
item.setCommand("#{menuBean.redirect}");
secondSubmenu.addElement(item);
model.addElement(secondSubmenu);
}
public MenuModel getModel() {
return model;
}
}
There are two built-in implementations; DefaultMenuModel should be preferred if your model is static and do not change once built and DynamicMenuModel is for models that are likely to change during the flow.
Development time of the new model took 4 days and it is really worth it, we have already fixed-closed various reported issues on old MenuModel which can’t be fixed without a reimplementation. New MenuModel will be available in upcoming PrimeFaces 4.0.