Using Twitter Bootstrap Navbar as a Wicket Component
All of you probably heard about Twitter Bootstrap, an awesome set of components allowing to create nice looking web pages and application without diving deeply into CSS/JS hacks. If you want to see what this library is capable of, please visit http://builtwithbootstrap.com/ and check how people use it to build their websites.
But this post isn’t supposed to be about Bootstrap itself. In a few next paragraphs I will present how I created reusable Wicket component containing Bootstrap top navigation bar menu. And final result using Wicket in our example web-app will look this way:
Before styling applied:
And what is most important, ready component can be used without any, really any modification in HTML files, everything is defined using pure Java:
1 2 3 4 5 6 7 8 9
If you are ‘show-me-the-code’ kind of guy, please go directly to my project on Github which contains working example of a web application with this navigation bar. If you want to read an explanation how this stuff works, please keep reading.
Step 1: Some preparations
NavBar component allows to display active menu item in a different way so user is able to determine where he/she is. So in our web application every web page should inform to which menu item it belongs so it could be highlighted accordingly.
So in our BasePage class we add a method:
returning defined enum:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
None value is used by home page because it does not belong to any particular menu item. Other pages (product pages, client, etc.) return one of other enum values presented above.
Step 2: Splitting markup into reusable pieces
Clean markup of Bootstrap NanBar may look like that:
And if you look attentively enough you will notice that it could be divided into smaller, reusable and independent elements:
each of these three
- inside red rectangle represents a single menu item and is almost the same, only active menu item has an additional class parameter.
- inside a yellow rectangle is a dropdown menu item and it contains label, some styling and two elements that are the same as a single menu items described above
So basically we should have three classes:
Panel class representing whole NavBar, that will be our TwitterBootstrapNavBarPanel
Panel class for single
- menu item - MenuLinkItem
Panel class for single
- dropdown menu – MenuDropdownItem - that also will contain a few MenuLinkItem elements to represent items inside this dropdown
So let’s start with the simplest one.
Step 3: Single menu item element - MenuLinkItem
Markup of this simple element is really non-complicated, only one link.
1 2 3
Its Java class is small and easy to grasp:
1 2 3 4 5 6 7 8 9 10
What we can see above is a simple panel accepting three parameters, standard Wicket element id, page link to place in this menu item and an indicator saying if this item should be displayed as an active. This is accomplished by adding a active class name to CSS class element.
Step 4: Dropdown menu item element - MenuDropdownItem
Now it’s getting a little harder as we want to create panel for our menu item containing a dropdown. Its markup:
1 2 3 4 5 6 7 8 9 10 11
So what we have here:
Wicket label (id=label) to display as a… label of this dropdown item
element containing list of
- elements represented by Wicket id=itemLinks
and finally, component wrapping everything above: id=itemContainer
And Java class for this panel:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
You may think Whoaa, this is a complicated one :) But relax, let me explain it step by step:
Here we create a container to add label and link items. Container is necessary because sometimes we would like to add active styling here so it has to be a Wicket component.
If this item should be active, add proper styling.
Add label element.
To render all item links in our dropdown we need a repeater. Wicket provides many repeater components but why we use RepeatingView? Because this one does not produce any additional markup and renders only inside markup where it is located (more details in javadoc). So in our case, it renders as a few
- .. elements without any additional html which is good to keep everything in line with Twitter Bootstrap styling.
For every link passed to our dropdown item we create new MenuLinkItem (do you remember when I underlined that dropdown will contain list of menu item elements?)
And that’s all, this component is clear now, isn’t it? :)
Step 5: Merging everything together
So we have two components ready to use in our main panel. Now it is time to introduce panel class and markup – TwitterBootstrapNavBarPanel. Markup luckily isn’t complicated:
1 2 3 4 5 6 7 8 9 10 11 12 13
This is a link with a label to redirect user to home page of our application.
This is a repeater to render all menu items (simple ones and dropdown as well)
Although the markup is not difficult to understand even at first glance, Java class is different and needs more detailed explanation. Because I wanted NavBar creation process to be as seamless as possible I used fluent interface with Builder pattern. So first, let’s concentrate on this element:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
So what’s happening here:
Our panel needs three mandatory things: Wicket component id, application name to render a label and home page class to create link so those trhee things will go to the Builder constructor
This method is responsible for collecting data for simple menu item so we need a menu item enum and class of the page that we want link to in the navigation bar
To gather all the data we use Google Guava Multimap with MeniItemEnum as a key and a Bookmarkable Links as a values. Multimap is a kind of map which allows multiple values for a single key.
But for a simple menu item we don’t want to have a more than one menu item duplicated in the navigation bar so we prevent it with a Preconditions check.
For a simple item we want to have a label equal to MenuItemEnum label so we add body to the link.
And put link in our multimap.
Now let me explain two last methods in the Builder class:
1 2 3 4 5 6 7 8 9 10
This method is used to add elements to the dropdown menu item. Here we allow to multimple values for the same menu item (as we will render them as a dropdown under single label). Additionally in the params list we need a label to each link as enum label will be used to render menu item itself and not a links inside it.
And when we’re ready we execute build() that calls private panel constructor.
Step 6: Panel class
We have everything set up, Builder has all the data we need to create our panel so let’s go to its constructor.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
Create link to the home page
Set its label
Create empty repeater
For each key from Multimap …
Get collection of links to place in current menu item
If there is only one link, add simple menu item (MenuLinkItem element)
Otherwsie, create MenuDropdownItem with collection of links
And that’s all. We went through the complete process of building reusable Wicket component based on the top of existing Twitter Bootstrap UI framework. And now it is easy to reuse it in a few next web applications we will create with Wicket.
Of course styling (colors, fonts, etc.) might be different but when we create an internal application for an insurance company or for a bank, they don’t expect UI to be really, really, really awesome. It just should look nice and that’s all. If you have such requirements, Twitter Bootstrap is the tool to choose. And when you encapsulate it with your Java web framework of choice you will get ready to use element that just works.
How-to, Java, Wicket