Vue.js with Liferay DXP

July 17, 2017

Vue.js ( is an open-source progressive JavaScript framework for building user interfaces. The creator of Vue.js worked in the AngularJs team, so this framework have some similarities with AngularJs. It is a very small library and due to its design is very easy to integrate with other framework. It is a candidate to use for creating portlets for Liferay

Hello world!

The first thing is import the library,

<script src=""></script>

As I am playing with Liferay themes, I had imported Vue.js in my own theme, but you can import in your portlet. You only need to add these lines:


    define._amd = define.amd;

    define.amd = false;


<script src=""></script>


    define.amd = define._amd;


Read more about this topic in

You can copy these two sections (html and JavaScript code) in your view.jsp file.

<div id="app">

  {{ message }}



  var app = new Vue({

    el: '#app',

    data: {

      message: 'Hello world!'




You can think about this sections in this simple way: the Vue.js application (JavaScript code) and the place where is going to be deployed (html code).

Noticed that the application has the property el with the value #app, this means that we must have an element in our html with id app.

In the application, we have a section data, every object we declared here is going to be accessible from everywhere of our application. As we have in our template {{ message }} Vue.js renders Hello world !. The same magic that AngularJs has.

The result of this as you expected is:

Expected result

Filter a list of countries

We just see the basics of Vue.js, now it is time for a more complex example.

I have created a method that gives a list of countries with their international code. You can see the code in the repository, but for this article, you only need to know that this is the line to include.

<portlet:resourceURL id="/countries" var="countriesURL" />

As in AngularJs there are directives that you can uses in your html code, in Vue.js all the custom directives starts with “v-“. If we want to iterate over a list of elements, there is the directive v-for

     <li v-for="country in countries">

As you imagine Vue.js iterates over the variable countries and creates a li element for each country.  Where is defined the variable countries?

The place to define this variable is in data section.

data: {
             message: 'Hello World!',
             countries: []

We have declared an empty array, which we are going to fill with countries using an AJAX call.

        created: function () {
         methods: {
             fetchData: function () {
                 $.getJSON("<%= countriesURL%>", function(result){
                     this.countries = result;

We have declared a function fechData inside methods section, as the fields defined in data section, every function declared here is accessible in all Vue.js application. This means that we can insert a button and call our function every time you push the button.

<button v-on:click=”fetchData()”>Load countries</button>

As we want have the data available as the time the application is created, we use the created section.

Due how is designed, Vue.js does not have by default the ability of making AJAX request. We can use Vue Resource ( which implies load another library. On the other hand, as Liferay loads a version of jQuery, I decided use this library.


Add a filter

Now we are going to add a filter,

<input type="text" v-model="keyword" placeholder="Search Title..."/>

A simple text input with the directive v-model. This directive creates a two-way binding for the variable keyword. This means that every time I write in the textbox, the value of the keyword variable is changed. We are going to use this variable for create a new filtered list.

         <li v-for="country in filteredList">
         </li>    </ul>

The new list is created in computed section, this is a method that will run when any variable inside changes his value.

computed: {
             filteredList: function() {
                 return this.countries.filter(function(element) {

The result is:


All the code is available in this repository

About the author: Carlos García
Join us