New UI Features in Liferay Portal 6.2

This article outlines some of the big changes that have been made to the UI in Liferay Portal 6.2, and how to work with them.

Liferay Portal 6.2 brings a set of improvements to the usability and user interface. Several components have been reworked; some of them are inherited from AlloyUI 2.0, and others have been developed directly on the portal. Noticeable features include:

  • Changes to the control panel
  • A reduced number of pop-ups
  • More responsive web design support

All of these features—and more—make the portal more usable and versatile and will allow Liferay to keep growing without increasing the complexity. This tutorial will walk you through some of the changes in Portal 6.2, using examples and screen-shots.

Table of Contents

  1. Features
  2. Building a Theme
  3. Accessing Liferay Services via JSONWS


Features

Twitter Bootstrap

Liferay provides support for Twitter Bootstrap CSS and HTML markup out of the box. AlloyUI powers the JavaScript that adds behavior to the Bootstrap components. AlloyUI uses a 1:1 translation from Less to Sass available on the alloy-bootstrap repository. Note that the way Liferay implements the translation adds minimal extra style definitions for AlloyUI.

Some of the benefits of using Bootstrap are:

  • Themes built for Liferay can be based on Bootstrap themes. There are quite a few of them (e.g. wrapbootstrapbootswatch, etc.)
  • Portlet developers can use the Bootstrap mark-up and Bootstrap components to build a nice looking UI faster than if they use responsive layouts.
  • * Content authors can use Bootstrap mark-up and styles to create beautiful looking advanced content that looks nice and is consistent with the rest of the UI.

The ability to use Bootstrap for web content is a side effect of its use in other applications.Twitter Bootstrap already has good documentation that you can access following the links above. Any HTML markup can be copied from Twitter Bootstrap documentation page and pasted inside Liferay portlets or contents. This facilitates development process and gives security to all layers of developers- from web designers to anyone who doesn’t like aligning pixels during development.

Example

For example, when creating a table in a web content, without Bootstrap capabilities it looks like this:

```html <table border="1" cellpadding="1" cellspacing="1" style="width: 500px;"> ```

01.PNG

With Bootstrap, the markup is simpler and produces a better result:

```html <table class="table table-striped table-bordered"> ```

02.png

Each of these values of the class attributes provides one feature:

  • `table` sets the base styles
  • `table-striped` colors alternative rows differently
  • `table-bordered` draws the borders around the table

Bootstrap also provides nice effects for images: rounding the borders, making images circular and adding a polaroid-like frame around it. These benefits exist without editing HTML.

03.png

  • `img-rounded` for rounded corners
  • `img-circle` to get an image with the shape of a circle
  • `img-polaroid` to get a nice frame around the image

Note: Before you save content, the WYSIWYG editor is not aware of Bootstrap, so clicking out of "Source" mode won't be enough to preview these changes. To preview changes with Bootstrap, click the "Basic Preview" button at the top of the web content form.

Font Awesome Icons

Liferay Portal 6.2 ships with its own version of Font Awesome. Font Awesome is a full suite of 361 pictographic icons for easy scalable vector graphics on websites.

Add Panel

The new “add panel” now provides ability to add content, applications and pages from the same place.

Add content panel: Lists all recent content and its previews, the user can drag and drop any of them to display on the portal.

 04.png

Add application panel: Lists all available portlets, the user can drag and drop any of them to display on the portal.

05.png

 

Add page panel: Pages can be created from this panel, the page type and layout can be selected.

Navbar

06.png

In order to standardize navigation through the portal, one of the new components put in place is the new<aui:nav-bar>, <aui:nav> and <aui:nav-item>. Navbars are responsive meta components that serve as navigation headers for your application or site.

07.png

<aui:nav-bar>
   <aui:nav>
       <aui:nav-item href="http://liferay.com" label="Liferay website" selected='<%= true %>' />
   </aui:nav>
</aui:nav-bar>

Reference jukebox/blob/master/sdk/portlets/jukebox-portlet/docroot/html/artists/toolbar.jsp

Available <aui:nav-bar> options:

Option Description

cssClass

The css class to be applied to the nav bar search wrapper element.
id A custom id to be applied on the nav bar search wrapper element.


Other options can be passed to <aui:nav>:

Option Description
ariaLabel W3C ARIA label for accessibility, see ARIA States and Properties
ariaRole W3C ARIA role for accessibility, see ARIA States and Properties.
collapsible Add ability to be collapsed (and are toggleable) in mobile views and become horizontal as the available viewport width increases.
cssClass The css class to be applied to the nav search wrapper element.
file A custom file path to be used.
icon Icon to be displayed on the collapsible panel in order to toggle the view.
id A custom id to be applied on the nav bar search wrapper element.
searchContainer A SearchContainer instance.
userNamespace Whether will use the portlet namespace on the element.

 

Available <aui:nav-item> options:

Option Description
anchorCssClass The css class to be applied to the nav bar search anchor element.
anchorData Map object to be translated to HTML5
anchorId A custom id to be applied on the nav bar search anchor element.
ariaLabel W3C ARIA role for accessibility, see ARIA States and Properties.
ariaRole W3C ARIA label for accessibility, see ARIA States and Properties.
cssClass The css class to be applied to the nav item search wrapper element.
data attributes to the anchor element.
dropdown Whether can host nested nav items to be displayed as a dropdown menu.
href The href of the anchor element.
iconCssClass The icon css class to be displayed next to the label.
id A custom id to be applied on the nav bar search wrapper element.
label The label of the nav item.
localizeLabel Whether the label should be localized.
selected Whether the nav item is selected.
state The state of the nav item, could be active or selected
title The title of the anchor.
toggle Toggle dropdown menu visibility.
useDialog Open the anchor href inside a dialog.
wrapDropDownMenu Wraps dropdown menu with a <ul>

 

Navbar Dropdown

A <aui:nav-item> can be nested in order to produce a drop-down menu, for instance:

<aui:nav-bar>
   <aui:nav>
       <aui:nav-item label="Liferay website" dropdown='<%= true %>'>
           <aui:nav-item href="http://liferay.com" label="Liferay portal" />
           <aui:nav-item href="http://in.liferay.com" label="Liferay Social Office" />
       </aui:nav-item>
   </aui:nav>
</aui:nav-bar>

08.png

Advanced Search

The new UI of advanced search provides a faster way to expand the search options.

09.png

Like on previous versions of Liferay, this functionality uses a <liferay-ui:search-toggle> taglib. The search toggle taglib can be placed inside a <aui:nav-bar> wrapped by a <aui:nav-bar-search>outputtingBootstrap HTML markup in order to provide the look and feel shown above.

<aui:nav-bar>
   <aui:nav-bar-search>
       <div class="form-search">
           <liferay-ui:search-toggle buttonLabel="search">
               <aui:fieldset>
                   <aui:input label="name" />
                   <aui:input name="bio" />
               </aui:fieldset>
           </liferay-ui:search-toggle>
       </div>
   </aui:nav-bar-search>
</aui:nav-bar>

Reference jukebox/blob/master/sdk/portlets/jukebox-portlet/docroot/html/artists/toolbar.jsp

Available <aui:nav-bar-search> options:

Option Description
cssClass The css class to be applied to the nav bar search wrapper element.
id A custom id to be applied on the nav bar search wrapper element.
file A custom file path to be used.
searchContainer A SearchContainer instance

 

<aui:nav-bar>

   <aui:nav-bar-search cssClass="pull-right" file="/html/portlet/directory/user_search.jsp" searchContainer="<%= userSearchContainer %>" />
</aui:nav-bar>

Dockbar

Dockbar is a very important portlet for Liferay administrators and developers- it continues to evolve, adding more and more features with each new version. All the markup of the Dockbar comes from the Dockbar portlet. In Liferay 6.2 it has been split into two sections. The first section (top right blue bar) contains navigation menus, the second (left center, the light blue bar) contains the Add, Mobile preview and Edit shortcuts.

10.png

Keep in mind that both sections of Dockbar come from the same portlet and share the same HTML markup. The split visual style is all done in CSS by the theme through defining .dockbar-split css class, see Github for more information.

Control Panel

The Control Panel was introduced in Liferay 5.2 as a way to provide a central location to manage the whole portal, including all of its sites. Previously, administrators had to build their own administration UI by manually adding portlets to pages. In the new version of Liferay the Control Panel has been redesigned to make it more usable and versatile. The main changes on 6.2:

  • "My Account" administration has been moved out of the Control Panel.
  • "Site Administration" has been moved out of the Control Panel

11.png

Form Navigator

Form navigator gives Liferay the ability to divide content into sections. It uses Bootstrap tabs enhanced by AlloyUI JavaScript.

12.png

<%
String[] categoryNames = new String[] {"Section"};
String[][] categorySections = { new String[] { "look-and-feel", "logo", "javascript", "mobile-device-rules" } };
%>

<liferay-ui:form-navigator
   categoryNames="<%= categoryNames %>"
   categorySections="<%= categorySections %>"
   jspPath="/html/portlet/jukebox/"
   showButtons="<%= true %>"
/>

Available <liferay-ui:form-navigator> options:

Option Description
backURL If the section redirects the page, this url will be used to be the destination when back button is clicked.
categorySections Divide the categories into sections.
categoryNames Name of the sections to display, each section name will match to a existing file into the jspPath folder
displayStyle When panel is passed, will display a panel style, otherwise displays like tabs.
formName The form name that wraps the form navigator.
htmlBottom HTML string to be placed on the bottom of the form navigator.
htmlTop HTML string to be placed on the top of the form navigator.
jspPath Path to be used as base path for the sections that requires server side. The file will match with the categoryNames value.
showButtons Whether submit and cancel buttons are shown.

 

Modal

The previous Dialog of Liferay was totally revamped and is now called Modal. Modal is based on AlloyUI’s modal component. In order to instantiate a new modal, AlloyUI API could be used directly. Liferay, though, wraps helpful functionalities- such as always keeping the dialog maximized and centralized to the page. In order to inherit the presets available on Liferay we recommend using Liferay.Util.Window.getWindow.

Liferay.Util.Window.getWindow({ dialog: { centered: true, cssClass: 'jukebox-portlet', height: 300, modal: true, resizable: false, width: 500 }, title: Liferay.Language.get('my-portlet') });

Available Liferay.Util.Window.getWindow options:

Option Description
dialog.autoHeight Whether the modal should automatically fits vertically to the viewport
dialog.autoHeightRatio Defines the ratio the modal height should take.
dialog.autoSizeNode The node used to defines the dimensions of the modal.
dialog.autoWidth Whether the modal should automatically fits horizontally to the viewport.
dialog.autoWidthRatio Defines the ratio the modal with should take.
title The modal title.

Note that Liferay Modal extends the AlloyUI modal component, therefore all options from the core component are also available to the dialog configuration passed to this API.

Localization

You have several ways to display a localized string in Liferay. The first one is using <liferay-ui:message />taglib:

<liferay-ui:message key="x-albums" />

<liferay-ui:message arguments="1000" key="x-albums" />13.png

Or via JavaScript API:

var message = Liferay.Language.get('x-albums');

   alert( A.Lang.sub(message, { 0: '1000' }) );

Input Localized

A new localized input is also available with a more intuitive and easy to use interface.

When your entity field is defined as localized on META-INF/portal-model-hints.xml the <aui:input>taglib detects that, and the field will be rendered as a localized input.

14.png

<aui:input name="title" />

Mobile Device Preview

We cannot forget the importance of supporting mobile devices for the web portals. Liferay 6.2 comes with an awesome feature of mobile device preview. This feature helps the developer to perform a unit testing of the portal on different types of hand held devices like smart phones, tablets as well as desktop. This feature does not provide an accurate preview but at least major issues can be resolved before the portal is accessed.

> 15.png

Search Container

The search container feature is available since older Liferay versions and it is responsible for rendering tables using an easy API that integrates with the server side data. On Liferay 6.2 it was restyled and now uses Bootstrap table styles.

<liferay-ui:search-container
   emptyResultsMessage="there-are-no-entries"
   total="100"
>

   <liferay-ui:search-container-results
       results="<%= JukeboxServiceUtil.search(...) %>"
   />

   <liferay-ui:search-container-row
       className="com.liferay.jukebox.model.Artist"
       keyProperty="artistId"
       modelVar="artist"
   >
       <liferay-ui:search-container-column-text
           name="name"
           value="<%= HtmlUtil.escape(artist.getName(locale)) %>"
       />
   </liferay-ui:search-container-row>

   <liferay-ui:search-iterator />
</liferay-ui:search-container>

16.png

Input Date

The new input date is much more intuitive. It now allows the user to input dates in friendly way.

17.png

When your entity field is defined as type date on META-INF/portal-model-hints.xml the <aui:input>taglib detects that and the field will be rendered as a date input. Another way to instantiate input date field is using <liferay-ui:input-date> taglib.

<liferay-ui:input-date
   dayParam="startDateDay"
   dayValue="5"
   disabled="<%= false %>"
   firstDayOfWeek="1"
   monthParam="startDateMonth"
   monthValue="5"
   name="startDate"
   yearParam="startDateYear"
   yearValue="2014"
/>

Available <liferay-ui:input-date> options:

Option Description
cssClass The css class to be applied to the input date wrapper element.
disabled Whether the input date should be disabled.
dayParam Name of the day parameter sent to the server on submit the hosting form.
dayParamId Id of the day parameter sent to the server on submit the hosting form.
dayValue Value of the day.
monthParam Name of the month parameter sent to the server on submit the hosting form.
monthParamId Id of the month parameter sent to the server on submit the hosting form.
monthValue Value of the month.
name Name of the input that holds the friendly date.
yearParam Name of the year parameter sent to the server on submit the hosting form.
yearParamId Id of the year parameter sent to the server on submit the hosting form.
yearValue Value of the year.

 

Input Time

The new input time is much more intuitive. It now allows the user to input time in friendly way.

18.png

To instantiate input time field the <liferay-ui:input-time> taglib could be used.

<liferay-ui:input-time
   amPmParam="startDateAmPm"
   amPmValue="<%= 0 %>"
   dateParam="startDateTime"
   dateValue="<%= new Date() %>"
   disabled="<%= false %>"
   hourParam="startDateHour"
   hourValue="10"
   minuteParam="startDateMinute"
   minuteValue="30"
   name="startTime"
/>

Available <liferay-ui:input-time> options:

Option Description
amPmParam Name of the amPm parameter sent to the server on submit the hosting form.
amPmValue Value of the amPm.
cssClass The css class to be applied to the input time wrapper element.
dateParam Name of the date parameter sent to the server on submit the hosting form.
dateValue Value of the date.
disabled Whether the input date should be disabled.
hourParam Name of the hour parameter sent to the server on submit the hosting form.
hourValue Value of the hour.
minuteInterval Value of the amPm.
minuteParam Name of the minute parameter sent to the server on submit the hosting form.
minuteValue Value of the minute
name Name of the input that holds the friendly date.

 

Popover

The AlloyUI popover component is used everywhere in the new Liferay interface. Currently there is no wrapper for the AlloyUI popover API, so feel free to copy the examples from the website and use in Liferay.

19.png

<aui:script use="aui-popover">
new A.Popover({
   align: {
       node: '#triggerElement'
   },
   toolbars: {
       header: [
           { label: 'Save', primary: true, icon:'icon-heart' },
           { label: 'Cancel' }
       ]
   },
   bodyContent: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.',
   trigger: '#triggerElement'
}).render();
</aui:script>

For more options available on Popover visit AlloyUI popover component page.

Liferay Panel

Panel is used to group sections and display an accordion-like interface. A panel usually is wrapped by a <liferay-ui:panel-container> taglib containing one or more <liferay-ui:panel> items.

20.png

<liferay-ui:panel-container extended="<%= true %>" id="jukebox">
   <liferay-ui:panel collapsible="<%= true %>" id= panel1" title="panel1">
       Panel 1
   </liferay-ui:panel>
   <liferay-ui:panel collapsible="<%= true %>" id="panel2" title="panel2">
       Panel 2
   </liferay-ui:panel>
</liferay-ui:panel-container>

Another available style is to display a simpler panel, also known as a not extended panel. This could be set through extended option.

21.png

<liferay-ui:panel-container extended="<%= true %>" id="jukebox">
   <liferay-ui:panel collapsible="<%= true %>" extended="<%= false %>" id="panel1" title="panel1">
       Panel 1
   </liferay-ui:panel>
   <liferay-ui:panel collapsible="<%= true %>" extended="<%= false %>" id="panel2" title="panel2">
       Panel 2
   </liferay-ui:panel>
</liferay-ui:panel-container>

Available <liferay-ui:panel-container> options:

Option Description
accordion Whether the panel should behave like an accordion.
cssClass The css class to be applied to the panel container wrapper element.
id The id of the panel container element.

Available <liferay-ui:panel> options:

Option Description
accordion Whether the panel should behave like an accordion.
collapsible Whether the panel should be collapsible.
cssClass The css class to be applied to the panel wrapper element.
defaultState Default state of the panel.
extended Whether the panel should display the extended interface.
helpMessage The help message displayed when hover the panel header.
iconCssClass The icon css class to be displayed next to the title.
id The id of the panel element.
parentId The id of the panel parent element.
persistState Whether the panel state should be persisted into the database.
state Could be open or closed.
title The title of the panel.

 

Layout Templates

In order to organize how the portal is going to display portlets into rows and columns Liferay provides a flexible way to create layout templates. In previous versions of Liferay AlloyUI 1.0 CSS grid system were used. For example, let's compare the 2_columns_i.tpl from Liferay 6.1 with 6.2.

<div class="columns-2" id="main-content" role="main">
   #if ($browserSniffer.isIe($request) && $browserSniffer.getMajorVersion($request) < 8)
       <table class="portlet-layout">
       <tr>
           <td class="aui-w50 portlet-column portlet-column-first" id="column-1">
               $processor.processColumn("column-1", "portlet-column-content portlet-column-content-first")
           </td>
           <td class="aui-w50 portlet-column portlet-column-last" id="column-2">
               $processor.processColumn("column-2", "portlet-column-content portlet-column-content-last")
           </td>
       </tr>
       </table>
   #else
       <div class="portlet-layout">
           <div class="aui-w50 portlet-column portlet-column-first" id="column-1">
               $processor.processColumn("column-1", "portlet-column-content portlet-column-content-first")
           </div>

           <div class="aui-w50 portlet-column portlet-column-last" id="column-2">
               $processor.processColumn("column-2", "portlet-column-content portlet-column-content-last")
           </div>
       </div>
   #end
</div>

On Liferay 6.2, Twitter Bootstrap's layoutsgrid system and fluid grid system are fully available. Other advantage of using Bootstrap layout capabilities is responsive web design features, for instance, on smaller screens, like those of phones, the columns will become fluid and display below each other automatically.

<div class="columns-1-2-1" id="main-content" role="main">
   <div class="portlet-layout row-fluid">
       <div class="portlet-column portlet-column-only span12" id="column-1">
           $processor.processColumn("column-1", "portlet-column-content portlet-column-content-only")
       </div>
   </div>

   <div class="portlet-layout row-fluid">
       <div class="portlet-column portlet-column-first span8" id="column-2">
           $processor.processColumn("column-2", "portlet-column-content portlet-column-content-first")
       </div>

       <div class="portlet-column portlet-column-last span4" id="column-3">
           $processor.processColumn("column-3", "portlet-column-content portlet-column-content-last")
       </div>
   </div>

   <div class="portlet-layout row-fluid">
       <div class="portlet-column portlet-column-only span12" id="column-4">
           $processor.processColumn("column-4", "portlet-column-content portlet-column-content-only")
       </div>
   </div>
</div>

Liferay 6.2 2_columns_i.tpl layout template uses Twitter Bootstrap's layoutsgrid system and fluid grid system, note the usage of row-fluid and span*.

Fixed Layouts

In order to create fixed layouts, Bootstrap provides a common fixed-width (and optionally responsive) layout with only <div class="container"> required.

22.png

<body>
 <div class="container">
   ...
 </div>
</body>

Fluid Layouts

To create a fluid, two-column page with <div class="container-fluid"> — great for applications and docs.

23.png

<div class="container-fluid">
 <div class="row-fluid">
   <div class="span2">
     <!--Sidebar content-->
   </div>
   <div class="span10">
     <!--Body content-->
   </div>
 </div>
</div>

Responsive Utility Classes

For faster mobile-friendly development, use these utility classes for showing and hiding content by device. Below is a table of the available classes and their effect on a given media query layout (labeled by device). They are already included in Liferay portal. For more reference check Twitter Bootstrap's responsive documentation.

Class Phones (767px and below) Tablets (979px to 768px) Desktops (Default)
.visible-phone Visible Hidden Hidden
.visible-tablet Hidden Visible Hidden
.visible-desktop Hidden Hidden Visible
.hidden-phone Hidden Visible Visible
.hidden-tablet Visible Hidden Visible
.hidden-desktop Visible Visible Hidden

 

How do I layout features on portlets?

Liferay popular <aui:layout>, <aui:column> are deprecated on Liferay 6.2 since they still use old AlloyUI grid system.

<aui:layout>
   <aui:column columnWidth="25">
       <liferay-util:include page="/html/portlet/jukebox/column1.jsp" />
   </aui:column>
   <aui:column columnWidth="75">
       <liferay-util:include page="/html/portlet/jukebox/column2.jsp" />
   </aui:column>
</aui:layout>

In order to have full advantage of Bootstrap on your layouts you should use the brand new <aui:row> and<aui:col> taglibs, which provides a very similar API, see the following example of the new taglibs.

<aui:row>
   <aui:col width="25">
       <liferay-util:include page="/html/portlet/jukebox/column1.jsp" />
   </aui:col>
   <aui:col width="75">
       <liferay-util:include page="/html/portlet/jukebox/column2.jsp" />
   </aui:col>
</aui:row>

Available <aui:row> options:

Option Description
cssClass The css class to be applied to the row wrapper element.
id A custom id to be applied on the row wrapper element.
fluid Whether the column should be .row-fluid

Available <aui:col> options:

Option Description
cssClass The css class to be applied to the column wrapper element.
id A custom id to be applied on the column wrapper element.
offset Move columns to the right using .offset* classes
offsetWidth Move the columns to the right using percentage, it converts the percentage to the closest .offset* value
span As this is a 12-column grid, each .span* spans a number of those 12 columns, and should always add up to 12 for each row (or the number of columns in the parent).
width Width in percentage that the column should be, it converts the percentage to the closest .span* value.

 

Building a Theme

Liferay and AlloyUI use a 1:1 translation from Less to Sass available on alloy-bootstrap repository. Liferay’s translation adds minimal extra style definitions to the code. The new Liferay classic theme uses Bootstrap core files in order to be generated. This flexibility brings powerful capabilities to Liferay. During theme development, it is possible to redefine parts of Bootstrap core before compiling the generated CSS file. For example, it is possible to tweak the variables on Bootstrap file that define base colors for Bootstrap.

Creating a Theme

Navigate to the material on the folder liferay-client-park-group/liferay-plugins-sdk-6.2.0/themes/park-theme/ previously created for you.

24.png

Deploy the theme so that Liferay copies the files from the parent theme. Once the theme is deployed the theme folder will look like this:

25.png

File Description
aui This contains a copy of AlloyUI Twitter Bootstrap's theme.
_aui_custom.scss Custom file to overwrite AlloyUI CSS classes.
_aui_variables.scss Custom file to overwrite AlloyUI theme variables.
_liferay_custom.scss Custom file to overwrite Liferay CSS classes.

If you are extending Bootstrap css classes or variables you should do inside this file, not custom.css. It's possible to customize the theme in the SASS level, that means that you can overwrite, extend or customize any of the AlloyUI CSS classes, including Bootstrap's. Let's see it in action.

26.png

On the created theme, copy _aui_variables.scss to _diffs/css/ folder and modify the value of the following two variables.

...
$navbarBackground: #FF0000;
$navbarBackgroundHighlight: #FF0000;
...

Redeploy your theme and notice that it redefined the background color of all navbar components. You can feel free to use any Sass feature to extend the existing functionality available on the theme.

27.png

Keep in mind you can use all features of Compass inside your Liferay theme.

Accessing Liferay Services via JSONWS

Liferay can expose any generated entity via a nice and easy to use web services API. To discover what is available open http://localhost:8080/api/jsonws on your Liferay instance.

Liferay.Service({
   "$user[firstName,emailAddress] = /user/get-user-by-id": {
       "userId": 10201,
       "$contact = /contact/get-contact-by-id": {
           "@contactId" : "$user.contactId"
       }
   }
},
function(obj) {
  console.log(obj)
});

For more information visit the Liferay’s JSON documentation.

Additional Information

A great resource in helping to understand the technical changes that have taken place is to follow the original ticket story on Liferay's issue tracker.

Was this article helpful?
0 out of 0 found this helpful