2.2/3.0 Menu/MenuItem Feature

UI Components for JSF
User avatar
gertbeedfrobe
Posts: 6
Joined: 21 Jul 2010, 16:47

18 Feb 2011, 20:28

All,

Was wondering if anyone has given though to providing an indicator for the "currently selected" menu item. I was able to add this functionality to 2.1 using an action listener that stored state information of the component id selected, and an EL function that determines the active menu item, based on the menuitem id and currently selected id as follows:

<p:menuitem value="General Information" id="general" process="@form"
actionListener="#{navigationBean.changeState}"
update="centerContent navMenu" ajax="true"
styleClass="#{customTagLib:determineActiveMenuItemStyle('general',
'general',navigationBean.currentState, 'ui-state-hover ui-corner-all')}" />

public static String determineActiveMenuItemStyle(String menuItemId, String defaultMenuItemId, String activeMenuItemId, String activeCssStyle) {
if (!defaultMenuItemId.equals("")
&& menuItemId.equals(defaultMenuItemId) && activeMenuItemId.equals("")) {
return activeCssStyle;
} else if (menuItemId.equals(activeMenuItemId)) {
return activeCssStyle;
}
return "";
}

This approach fails with versions 2.2/3.0, and although the CSS class names have changed for the menuItem components, I think it's the trickery/hack I'm using to provide this functionality that's no longer compatible. You can see it in action here at http://psycodek.com/ . Maybe it doesn't make sense to add this feature as it would require some state saving mechanism? Not sure.

Thanks,

Nathan M.

dehlers1000
Posts: 34
Joined: 09 Feb 2011, 20:44

21 Dec 2011, 19:59

I am also looking for a solution but am unable to workout a good solution. Here is my work-around:

1) add another class

.ui-state-hover-test {
background: url("/PrimefacesTest/javax.faces.resource/themes/sam/images/sprite.png.jsf?ln=primefaces&v=2.2.1") repeat-x scroll left -1300px #BFDAFF border: 1px solid #D3D3D3;
color: #212121;
font-weight: normal;
}

The name has to be different than .ui-state-hover or Primefaces code will remove the style class.

2) Create a a navigation with session state that will hold all the menuitem buttons and provide an action.
public String menuAction() {
styleClassTest2 = "";
styleClassTest = "ui-state-hover-test";
return "pdfWizard?faces-redirect=true";
}
3) Create hyperlinks within the menuitem or the class cannot be be changed.
<p:menuitem>
<p:commandLink id="tab1" action="#{navBean.menuAction}" styleClass="#{navBean.styleClassTest}" ajax="false" >
<span title="Remove" class="ui-icon ui-icon-clipboard" style="float:left;"/><div style="float:right;">PDF Test</div>
</p:commandLink>
</p:menuitem>
<p:menuitem>
<p:commandLink id="tab2" action="#{navBean.menuActionTest2}" #{navBean.styleClassTest2} value="test2" ajax="false" />
</p:menuitem>

It is not elegant but it works. The part I don't like is that if a user uses the back button, the screen that is displayed will be out of sync with the selected button because the selected button will always be the active button until clicked.

Hope this helps.

smithh032772
Posts: 6144
Joined: 10 Sep 2011, 21:10

22 Dec 2011, 00:28

Wow, THANK YOU for posting/initiating this topic. This just motivated me to add some code to implement this type of menubar > selected menuitem feature. First, I want to share my code and then, later, I'd like to post some screen captures.

FYI: I replaced p:tabView with p:menubar sometime ago, and this concept is working as designed and perfectly for my use-case.

mcms.css

Code: Select all

/* default/non-selected menuitem style */
.orders-menuitem-text .ui-menuitem-text {
    font-size: 90% !important;
}

/* selected menuitem style */
.orders-menuitem-selected .ui-menuitem-text {
    font-size: 95% !important;
    font-weight: bolder !important;
}
bean: pf_OrdersController.java (ViewScoped)

Code: Select all

    private String pageEditCustomer, pageForEditMenu, editMenuItemSelected;

    /* constructor */
    public pf_OrdersController() {
        pageEditCustomer = "/orders/pf_EditCustomer.xhtml";
        pageForEditMenu = "/pageContent_blank.xhtml";
        editMenuItemSelected = "";
    } // pf_OrdersController()

    /* no need to share all getter/setters; will share those referenced by xhtml/jsf */

    /*
     * styleCSS="..." for Edit menubar to show which menuitem is selected
     */
    public String getCssForEditMenuItem(String editMenuItem) {
        String styleClass = new String();
        if (editMenuItem.equals(editMenuItemSelected))
            styleClass = "orders-menuitem-selected";
        else
            styleClass = "orders-menuitem-text";
        return styleClass;
    }

    public void setEditMenuItemSelected(String editMenuItemSelected) {
        this.editMenuItemSelected = editMenuItemSelected;
        
        if (editMenuItemSelected.equals("Destination")) {
            this.pageForEditMenu = destinationController.getPage(tableName, current, current.getOrderId());
        }
        else if (editMenuItemSelected.equals("Origin")) {
            this.pageForEditMenu = originController.getPage(tableName, current, current.getOrderId());
        }
        else if (editMenuItemSelected.equals("Ordered By")) {
            this.pageForEditMenu = pageEditCustomer;
        }
        else if (editMenuItemSelected.equals("Details")) {
            this.pageForEditMenu = "/orders/pf_EditDetails.xhtml";
        }
        else if (editMenuItemSelected.equals("Notes")) {
            this.pageForEditMenu = "/orders/pf_EditNotes.xhtml";
        }
        else if (editMenuItemSelected.equals("Routes")) {
            this.pageForEditMenu = "/orders/pf_EditRoutes.xhtml";
        }
        else if (editMenuItemSelected.equals("Pricing")) {
            this.pageForEditMenu = getViewPage("OrderCostDetails", new ArrayList(current.getOrderCostDetails()));
        }
        else if (editMenuItemSelected.equals("Payment")) {
            this.pageForEditMenu = "/orders/pf_ViewPayment.xhtml";
        }
        else if (editMenuItemSelected.equals("Status")) {
            this.pageForEditMenu = "/orders/pf_ViewStatus.xhtml";
        }
        else if (editMenuItemSelected.equals("Attractions")) {
            this.pageForEditMenu = getViewPage("Attraction", new ArrayList(current.getAttractions()));
        }
        else if (editMenuItemSelected.equals("Contact Persons")) {
            this.pageForEditMenu = pointOfContactController.getPage(tableName, current, current.getOrderId());
        }
        else if (editMenuItemSelected.equals("Flights")) {
            this.pageForEditMenu = getViewPage("Flight", new ArrayList(current.getFlights()));
        }
        else if (editMenuItemSelected.equals("Hotels")) {
            this.pageForEditMenu = getViewPage("Hotel", new ArrayList(current.getHotels()));
        }
        else if (editMenuItemSelected.equals("Meal Stops")) {
            this.pageForEditMenu = getViewPage("MealStop", new ArrayList(current.getMealStops()));
        }
        else if (editMenuItemSelected.equals("Local Bus")) {
            this.pageForEditMenu = getViewPage("LocalBus", new ArrayList(current.getLocalBuses()));
        }
        
    }
    
    /* called when enduser clicks the Edit button */
    public String prepareEdit() {
        pageEditCustomer = "/orders/pf_EditCustomer.xhtml";
        pageForEditMenu = "/pageContent_blank.xhtml";
        editMenuItemSelected = "";
        getPageNavigation().setPage("/orders/pf_Edit.xhtml");
        return null;
    }
pf_EditMenuBar.xhtml

Code: Select all

<?xml version='1.0' encoding='UTF-8' ?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">
    
    <ui:composition>
        
        <p:menubar id="ordersEditMenuBar">

            <p:menuitem value="Destination" update=":orderEditForm:_ajax_status :orderEditForm:panelBelowEditMenu ordersEditMenuBar"
                        actionListener="#{pf_ordersController.setEditMenuItemSelected('Destination')}"
                        styleClass="#{pf_ordersController.getCssForEditMenuItem('Destination')}"/>
            
            <p:menuitem value="Origin" update=":orderEditForm:_ajax_status :orderEditForm:panelBelowEditMenu ordersEditMenuBar"
                        actionListener="#{pf_ordersController.setEditMenuItemSelected('Origin')}"
                        styleClass="#{pf_ordersController.getCssForEditMenuItem('Origin')}"/>
            
            <p:menuitem value="Ordered By" update=":orderEditForm:_ajax_status :orderEditForm:panelBelowEditMenu ordersEditMenuBar"
                        actionListener="#{pf_ordersController.setEditMenuItemSelected('Ordered By')}"
                        styleClass="#{pf_ordersController.getCssForEditMenuItem('Ordered By')}"/>
            
            <p:menuitem value="Details" update=":orderEditForm:_ajax_status :orderEditForm:panelBelowEditMenu ordersEditMenuBar"
                        actionListener="#{pf_ordersController.setEditMenuItemSelected('Details')}"
                        styleClass="#{pf_ordersController.getCssForEditMenuItem('Details')}"/>
            
            <p:menuitem value="Notes" update=":orderEditForm:_ajax_status :orderEditForm:panelBelowEditMenu ordersEditMenuBar"
                        actionListener="#{pf_ordersController.setEditMenuItemSelected('Notes')}"
                        styleClass="#{pf_ordersController.getCssForEditMenuItem('Notes')}"/>
            
            <p:menuitem value="Routes" update=":orderEditForm:_ajax_status :orderEditForm:panelBelowEditMenu ordersEditMenuBar"
                        actionListener="#{pf_ordersController.setEditMenuItemSelected('Routes')}"
                        styleClass="#{pf_ordersController.getCssForEditMenuItem('Routes')}"/>
            
            <p:menuitem value="Pricing" update=":orderEditForm:_ajax_status :orderEditForm:panelBelowEditMenu ordersEditMenuBar"
                        actionListener="#{pf_ordersController.setEditMenuItemSelected('Pricing')}"
                        styleClass="#{pf_ordersController.getCssForEditMenuItem('Pricing')}"/>
            
            <p:menuitem value="Payment" update=":orderEditForm:_ajax_status :orderEditForm:panelBelowEditMenu ordersEditMenuBar"
                        actionListener="#{pf_ordersController.setEditMenuItemSelected('Payment')}"
                        styleClass="#{pf_ordersController.getCssForEditMenuItem('Payment')}"/>
            
            <p:menuitem value="Status" update=":orderEditForm:_ajax_status :orderEditForm:panelBelowEditMenu ordersEditMenuBar"
                        actionListener="#{pf_ordersController.setEditMenuItemSelected('Status')}"
                        styleClass="#{pf_ordersController.getCssForEditMenuItem('Status')}"/>
            
            <p:menuitem value="Attractions" update=":orderEditForm:_ajax_status :orderEditForm:panelBelowEditMenu ordersEditMenuBar"
                        actionListener="#{pf_ordersController.setEditMenuItemSelected('Attractions')}"
                        styleClass="#{pf_ordersController.getCssForEditMenuItem('Attractions')}"/>
            
            <p:menuitem value="Contact Persons" update=":orderEditForm:_ajax_status :orderEditForm:panelBelowEditMenu ordersEditMenuBar"
                        actionListener="#{pf_ordersController.setEditMenuItemSelected('Contact Persons')}"
                        styleClass="#{pf_ordersController.getCssForEditMenuItem('Contact Persons')}"/>
            
            <p:menuitem value="Flights" update=":orderEditForm:_ajax_status :orderEditForm:panelBelowEditMenu ordersEditMenuBar"
                        actionListener="#{pf_ordersController.setEditMenuItemSelected('Flights')}"
                        styleClass="#{pf_ordersController.getCssForEditMenuItem('Flights')}"/>
            
            <p:menuitem value="Hotels" update=":orderEditForm:_ajax_status :orderEditForm:panelBelowEditMenu ordersEditMenuBar"
                        actionListener="#{pf_ordersController.setEditMenuItemSelected('Hotels')}"
                        styleClass="#{pf_ordersController.getCssForEditMenuItem('Hotels')}"/>
            
            <p:menuitem value="Meal Stops" update=":orderEditForm:_ajax_status :orderEditForm:panelBelowEditMenu ordersEditMenuBar"
                        actionListener="#{pf_ordersController.setEditMenuItemSelected('Meal Stops')}"
                        styleClass="#{pf_ordersController.getCssForEditMenuItem('Meal Stops')}"/>
            
            <p:menuitem value="Local Bus" update=":orderEditForm:_ajax_status :orderEditForm:panelBelowEditMenu ordersEditMenuBar"
                        actionListener="#{pf_ordersController.setEditMenuItemSelected('Local Bus')}"
                        styleClass="#{pf_ordersController.getCssForEditMenuItem('Local Bus')}"/>
            
        </p:menubar>

            
    </ui:composition>
    
</html>
Howard

PrimeFaces 6.0, Extensions 6.0.0, Push (Atmosphere 2.4.0)
TomEE+ 1.7.4 (Tomcat 7.0.68), MyFaces Core 2.2.9, JDK8
JUEL 2.2.7 | OmniFaces | EclipseLink-JPA/Derby | Chrome

Java EE 6 Tutorial|NetBeans|Google|Stackoverflow|PrimeFaces|Apache

sakkie6yster
Posts: 80
Joined: 23 Nov 2011, 08:46

23 Oct 2012, 16:26

I need exactly the same functionality but for a dynamic menuitem, i.e. I am building the menu items in java and was hoping there was a way I could use the
.setStyleClass("") method. Unfortunately does not work though as you can't pass in a MethodExpression. So how would one do this for a dynamic menu?
Anybody have any suggestions?
Primefaces 5.3, Extensions 4.0.0
Glassfish 3.1.2.2, Wildfly-10.0.0.Final
JSF 2.2

rafael
Posts: 6
Joined: 23 May 2012, 21:07

27 Mar 2013, 19:45

I did a simple approach

Code: Select all

<p:menuitem value="Adicionar" icon="ui-icon ui-icon-plus" ajax="false" style="#{menuBean.getMenuItemCss('addUser')}"
	 action="#{menuBean.redirect('addUser', '/pages/usuario/adicionarUsuario.jsf')}"/>
<p:menuitem value="Procurar" icon="ui-icon ui-icon-plus" ajax="false" style="#{menuBean.getMenuItemCss('findUser')}"
	 action="#{menuBean.redirect('findUser', '/pages/usuario/procurarUsuario.jsf')}"/>

Code: Select all

private String selectedMenuItem = "";

public String getMenuItemCss(String id) {
	if (id.equals(selectedMenuItem)) {
		return "font-weight: bold;";
	}
	return "";
}

public String redirect(String id, String url) {
	selectedMenuItem = id;
	return url;
}
Primefaces: 3.4
Mojara: 2.1.11
JBoss as 7.1.3

sakkie6yster
Posts: 80
Joined: 23 Nov 2011, 08:46

08 Apr 2013, 10:23

Hi Rafael,

that is a nice and clean solution. The problem I have is that I am unable to use the dynamic setting of the style when using a dynamic menu. For instance, if I create a menu item via code and set the style to "getMenuItemCss()", the method is never called:

Code: Select all

       item = new MenuItem();
        item.setValue("Menus");
        item.setIcon("ui-icon-folder-open");
        item.setUpdate("main-content main-menu growl");
        item.setActionExpression(expressionFactory.createMethodExpression(elContext, "#{dynamicMenu.setSelectedPage('admin-menus.xhtml')}", Void.class, new Class[]{String.class}));
        item.setStyle("#{dynamicMenu.getMenuItemCss('admin-menus.xhtml')}");
        item.setAjax(false);
Is this a bug? Should getMenuItemCss be called with a dynamic menu?
Primefaces 5.3, Extensions 4.0.0
Glassfish 3.1.2.2, Wildfly-10.0.0.Final
JSF 2.2

smithh032772
Posts: 6144
Joined: 10 Sep 2011, 21:10

08 Apr 2013, 15:07

sakkie6yster wrote:The problem I have is that I am unable to use the dynamic setting of the style when using a dynamic menu. For instance, if I create a menu item via code and set the style to "getMenuItemCss()", the method is never called:

Code: Select all

       item = new MenuItem();
        item.setValue("Menus");
        item.setIcon("ui-icon-folder-open");
        item.setUpdate("main-content main-menu growl");
        item.setActionExpression(expressionFactory.createMethodExpression(elContext, "#{dynamicMenu.setSelectedPage('admin-menus.xhtml')}", Void.class, new Class[]{String.class}));
        item.setStyle("#{dynamicMenu.getMenuItemCss('admin-menus.xhtml')}");
        item.setAjax(false);
Is this a bug? Should getMenuItemCss be called with a dynamic menu?
You need to create a new/separate topic and make sure you include 'dynamic menu' in your topic title/subject. Also, I fully recommend that you search this forum for keywords related to dynamic menus, createMethodExpression, etc...

It is quite obvious that (from what I can tell), everyone else that has shared their code is 'not' implementing dynamic menu. If you want to use this code, then create the static menu and get that working, instead.
Howard

PrimeFaces 6.0, Extensions 6.0.0, Push (Atmosphere 2.4.0)
TomEE+ 1.7.4 (Tomcat 7.0.68), MyFaces Core 2.2.9, JDK8
JUEL 2.2.7 | OmniFaces | EclipseLink-JPA/Derby | Chrome

Java EE 6 Tutorial|NetBeans|Google|Stackoverflow|PrimeFaces|Apache

sakkie6yster
Posts: 80
Joined: 23 Nov 2011, 08:46

08 Apr 2013, 15:13

Hi Howard,

do you have any idea if this would be possible with the dynamic menu though?
Primefaces 5.3, Extensions 4.0.0
Glassfish 3.1.2.2, Wildfly-10.0.0.Final
JSF 2.2

User avatar
andyba
Expert Member
Posts: 2473
Joined: 31 Mar 2011, 16:27
Location: Steinfeld, near Bremen/Osnabrück, DE
Contact:

08 Apr 2013, 15:13

I see that there are a couple of new members who are doing the usual thing and

1- not reading the forum rules
2- resurrecting old Threads.

I have already replied to one of the "offenders" already and they have done as they should, started a new Thread.
However this is getting to be a problem again and my patience is not boundless so reporting repeat offenders is something that I may have to resort to.
PF 4.x (Elite versions), PF 5, Pf 5.1, PF 6.0
Glassfish 4.1, Mojarra 2.x, Java 8, Payara 4.1.1.
If you haven't read the forum rules read them now

smithh032772
Posts: 6144
Joined: 10 Sep 2011, 21:10

08 Apr 2013, 15:24

andyba wrote:... reporting repeat offenders is something that I may have to resort to.
+1,000,000 Like!!! I will have to do that, 'too', since I do use the 'Report' button on topics, when it is spam or off-topic.

EDIT: Done! clicked the Report button and completed the form, accordingly. Thanks Andy!!!
Howard

PrimeFaces 6.0, Extensions 6.0.0, Push (Atmosphere 2.4.0)
TomEE+ 1.7.4 (Tomcat 7.0.68), MyFaces Core 2.2.9, JDK8
JUEL 2.2.7 | OmniFaces | EclipseLink-JPA/Derby | Chrome

Java EE 6 Tutorial|NetBeans|Google|Stackoverflow|PrimeFaces|Apache

Locked

Return to “PrimeFaces”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 30 guests