Using EXTJS with Liferay

As promised this blog post is a continuation of the previous one about RESTFul services (check the related blog)

On this blog post I will explain how to integrate an external javascript library - EXTJS with Liferay, combined with our Permission System.

I am going to use the same RESTFul APIs developed previously to provide the CRUD operations and use EXTJS to invoke these APIs via AJAX in order to build the UI.

Before starting to do this you should ask yourself:

 - Why do I want to use a third party library like EXTJS

 - Do I really need this library

 - Do I really really need this library

More than often the answer can be "no". Have in mind Liferay is build using AlloyUI and you have available the components of YUI so as a rule of thumb I would say, if possible, use the frameworks available.

This is for several reasons: 

 - We support AUI and have created all the components to meet our requirements

 - Using AUI will make your portlets look exactly the same so you gain consistency (think about if you want for example to have your portlets available in the marketplace or not)

 - AUI is integrated with our Liferay Themes engine

 - Your team of developers will need to understand AUI (at least how to use it) as it is everywhere in our source code, without knowing it you will be in trouble if you need to extend our code so you need to learn it anyways

But in some cases this might not be enough for you, so you need to look at other options.

Common frameworks of choice for the UI are JQuery, JSF, Vaading, GWT, etc

I am going to use EXTJS because I don't see a lot of examples elsewhere and it is a really good framework.

Take a look at the framework here

It has great support for dashboards and it is in general really powerful, so it might be a good choice for you.

Lets just have in mind a couple of things about javascript with portlets:

 - Sandbox your code - remember that you might have other portlets in a page so your code should not interfere with others

 - Namespace your functions - same reason, by using the portlet namespace for your functions and divs you are keeping your javascript code safe.

 - Put your javascript where it needs to be: in a js file if possible

Before proceeding I need to make a statement that I am not a javascript expert. There are a ton of liferay employees that can probably write the javascript code better than me, my point here is just to prove the concepts..

So you start by downloading the community version of ExtJS and put the files in a js folder inside my project.

The next thing I need to do is import the Ext files required to use them in my portlets. I will do that on my liferay-portlet.xml

ExtJs has several versions of the main js file you can import into your project. We are using the debug with comments version, so it is really easy to debug the extjs files and you can also read the comments.

In production do not use this version because it is a big js file, you have the trimmed version without comments you can import.

My project structure will consist on one init.jsp (using Liferay pattern of having a shared jsp with the imports), one main page called defaultView.jsp and two additional jsp one for the RESTFul example and another with mock data showing a complex dashboard running inside the portlet

for each of the two jsp I have created a javascript file where all the EXT code is.

On my main jsp I have two buttons that redirect to the two jsps depending on what you want to see.

So for that I created a couple of renderURL and assigned them with two aui buttons. This way if you click on RESTFul Data button you will se an EXT grid that is using the RESTFul APIs described in my last post, and if you click on Sample Form Dashboard you will see a complex dashboard using sample data.

I now need to tell Spring MVC to redirect me to the appropriate page depending on the renderURL selected

My next step is to develop the code for the Sample Form Dashboard javascript file. This code is just copied from one of the EXTJS examples online. The only difference is that I pass the divId as a parameter (the div that EXTJS should use to render the content). 

The javascript code is really extensive so you can find the js file here

See how easy it is to combine several different types of ext components into one screen, and quickly produce extremely complex UI

I then developed my FormDashboard.jsp to go along with it

 

Notice how I combine the use of jstl variables with javascript and jsp, passing my portlet namespace into the javascript function. 

In my init.jsp I defined the variables I need. And I don't use scriptlets because I have them and I think it polutes the code ( strange for a Liferay guy but true)

If you click on Sample Form Dashboard this is what you will see:

If you click on a company EXT updates the graphs to show the company value. This is a really awesome dashboard all in javascript!

So after this I created the RESTFulData.js code. I chose a Grid (similar to a data table) to present all of the existing Samples, allowing the users to Delete, Update and Create samples as well (see code here).

I start by defining a model, basically my JSON object HelloSample that you have seen in my previous post

EXT has great support for rest calls, by just defining a proxy and integrating it inside a Grid you are half done.

Also i use my config variable to obtain the permissions the user has. After defining my json store I just need to define my grid panel.

Notice how the columns are easy to define. Finally I add dockedItems to my grid panel to allow Add and Delete functions

 

Afterwards I just need to import the js file in my RESTFulData.jsp

Never mind about the permissions we are going to cover that next, but notice how I import the external JS file and namespace my js variables. The function itself is not namespaced so in the real world I would create an ext component instead of a function. The component could receive every configuration as parameters this way I would have sandboxed my code. But this is still safe, I use my portlet name as part of the function identifier so there is no issue about having two functions on the same page with the same name. If we add this portlet twice we simple use the same javascript function twice to create two grids but render to different ids so it will work anyways.

For this implementation I decided to create a config variable where I will add all of my runtime variables I will need in javascript (like portletUrls, permissions, etc) and pass that object into my javascript function

Now I need to tell EXT to disable or hide the buttons for CRUD operations the user does not have access to and so for that I will start by defining the liferay permissions I require. So in my source folder I created a folder called resource-actions and a file inside called default.xml

These are the permissions active for this portlet:

I then load the permissions to jstl variables on my jsp, in order to know what a user can or cannot do and pass these permissions to my config javascript var that goes straight into my JS function.

In my ext code I disable the buttons and operations a user is not entitled to do

Create:

Update:

Delete:

Remember you need to add the permissionChecking also to your service files, this way if a user does not have access to delete Samples he cannot invoke the REST service as well.

And here it is:

The grid:

If you have permissions you are able to add entries by pressing the add button

Notice the nice inline editing of EXT grid

If you select one row you are able to delete the entry (if you have permissions)

If you double click on a row you are able to change the content on the columns 

So as you can see it is not that hard to integrate an external third party JS framework, even a really complicated one like EXTJS.

I hope you liked it

 

 

 

Blogs
Excellent post!!! I happy to see this post as it gave clear a path for all developers who are struggling to include Ext JS with Lifeay.
I expected some server side verification for permissions. I expected that users who doesn't have permissions to be denied to access some urls. In this case, as simple user, if i know url, i can access any method.