12

I have a static menu in the sidebar which I include in every JSF page. The menu looks like so:

  <li class="nav-header">Item 1</li>
  <li class="active"><a href="index.xhtml">Item 2</a></li>
  <li><a href="new_workload.xhtml">Item 3</a></li>
  <li><a href="import_workload.xhtml">Item 4</a></li>

Adding a class="active" to the <li> highlights the menu. How do I go about making sure selected item is highlighted dynamically in JSF2?

I know PrimeFaces and RichFaces have ready made components for this, but I want to try a pure JSF 2 solution first. A pure client side JavaScript solution is also acceptable.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Ravi S
  • 231
  • 1
  • 5
  • 11

3 Answers3

34

You can get the current view ID in EL as follows

#{view.viewId}

So, this should do

class="#{view.viewId eq '/index.xhtml' ? 'active' : ''}"

It'd be easier to hold all those links in some List<Page> so that you can just do something like

<li class="nav-header">#{menu.header}</li>
<ui:repeat value="#{menu.pages}" var="page">
    <li class="#{view.viewId eq page.viewId ? 'active' : ''}">
        <h:link value="#{page.title}" outcome="#{page.viewId}" />
    </li>
</ui:repeat>

instead of copypasting the same piece of code over and over.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 5
    Thank you BaluSC.! What would newcomers to JSF do without you:-) Appreciate your patience in answering all these noob questions... – Ravi S Jun 19 '12 at 05:13
  • can you suggest some solution when menu item updates the partial page via ajax. and not the complete page is refreshed. i can do it with a javascript callback on menu click. but what could be a better approach. – hitesh israni Oct 10 '12 at 14:18
  • Thanks, @BalusC, you always save us. It's time to Stack Exchange to create a BalusC Response Community. kkk – Ascension Jul 30 '15 at 14:18
  • thank you @BalusC !! really this is an extra magic, but how to make it works with menus and sub-menus ? – Spartan Nov 18 '15 at 16:11
  • @Spartan: have `Page` a `List pages` property representing child pages. – BalusC Nov 18 '15 at 18:22
  • @BalusC : and what about the condition `"#{view.viewId eq page.viewId ? 'active' : ''}"` and how to get 2 parameters from `view.viewId` – Spartan Nov 18 '15 at 19:44
  • Do you recommend to store those pages in a database or just as List of a `@ApplicationScoped` bean? – alexander Dec 04 '15 at 23:19
  • Thanks for your answer BalusC How would you do it if the outcome page is always the same but with different parameters ? I tried something like: #{view.viewId eq '/tcsinstance.xhtml?tcs='+o.dir ? 'active' : ''} But this doesn't work... Full Link looks like this: http://localhost:8080/tcs-web/faces/tcsinstance.xhtml?tcs=tcs02_7040&host=mqzhltcs02&port=7040 Thank you! – Sundaze Dec 01 '16 at 13:16
1

I've used @BalusC idea plus his other tip at 12473461 but with some modification:

<ul>
  <li class="#{view.viewId eq '/admin/index.xhtml' ? 'active' : ''}"><h:link value="Main" outcome="main"/></li>
  <li class="#{fn:startsWith(view.viewId, '/admin/sess1/') ? 'active' : ''}"><h:link value="Session 1" outcome="sess1"/></li>
  <li class="#{fn:startsWith(view.viewId, '/admin/sess2/') ? 'active' : ''}"><h:link value="Session 2" outcome="sess2"/></li>
  <li class="#{fn:startsWith(view.viewId, '/admin/sess3/') ? 'active' : ''}"><h:link value="Session 3" outcome="sess3"/></li>
</ul>
Community
  • 1
  • 1
Ramon Chiara
  • 616
  • 6
  • 8
0

My solution is based on custom component:

<?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:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:composite="http://java.sun.com/jsf/composite" xmlns:c="http://java.sun.com/jsp/jstl/core" >
<composite:interface>
    <composite:attribute name="outcome" />
    <composite:attribute name="label" />
</composite:interface>

<composite:implementation>
    <li class="menuItem #{view.viewId == cc.attrs.outcome ? 'active' : ''}">
        <h:outputText value="#{cc.attrs.label}" rendered="#{view.viewId eq cc.attrs.outcome}"/>
        <h:link outcome="#{cc.attrs.outcome}" value="#{cc.attrs.label}" rendered="#{view.viewId ne cc.attrs.outcome}" />
    </li>
</composite:implementation>
</html>

Used in code:

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:my="http://java.sun.com/jsf/composite/my">
...
<ul class="nav">
     <my:menuItem outcome="/home.xhtml" label="Home" />
</ul>