ddraper

Using vue.js with Aikau

Blog Post created by ddraper on Oct 7, 2016

Introduction

In the recent State of JavaScript 2016 survey results I noticed that vue.js was gaining massively in popularity as a front-end framework so I thought it might be an interesting experiment to see how easily it could be leveraged within Aikau. I'll admit that I haven't delved to deeply into vue.js in any meaningful way beyond reading the first few pages of the guide so don't expect this to provide any earth-shattering insight into what you can and can't do with it, and I have no real opinion on it yet beyond having noticed it's growing adoption. This post can be considered a more general guide to how you can go about using the JS framework of your choice within Aikau.  In this example I'm going to create an extension that provides a Share dashlet rendering a very simple vue.js component (the obligatory "Hello World" component in fact).

 

Hello Vue.js

The first thing I noticed when going through the guide was how simple it was - write a template and create a component that targets that template. This approach lends itself very nicely to Aikau which breaks widgets down into JS, CSS, templates and localization files. The template for the example looks like this:

 

<div id="app">
  {{ message }}
</div>

 

...and the JavaScript looks like this:

 

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})

 

The idea is that the Vue instance uses the el CSS style selector to target the fragment of DOM to convert into a component and substitutes the {{ message }} token with the value of message.

 

Adding a Package Declaration

The other great thing I found out was that vue.js is written to support AMD. This means that we can just declare it as a new package for Aikau to consume. I downloaded the source files and placed them in the META-INF/js/lib folder of my extension JAR and defined a couple of new packages ("vue" for the vue.js libary, and "blog" for my custom components) like this:

 

<extension>
  <modules>
    <module>
      <id>vue.js extension</id>
      <auto-deploy>true</auto-deploy>
      <evaluator type="default.extensibility.evaluator"/>
      <configurations>
        <config evaluator="string-compare" condition="WebFramework" replace="false">
          <web-framework>
            <dojo-pages> 
                <packages> 
                    <package name="vue" location="js/lib" main="vue"/> 
                    <package name="blog" location="js/blog"/> 
                </packages>
            </dojo-pages>
          </web-framework>
        </config>
      </configurations>
    </module>
  </modules>
</extension>

 

Creating a Widget

The next step was to create a widget that made use of the vue.js package. This widget would comprise of the JavaScript file and an HTML template file. The JavaScript file looks like this:

 

define(["dojo/_base/declare",
        "dijit/_WidgetBase", 
        "dijit/_TemplatedMixin",
        "dojo/text!./templates/VueExample.html",
        "alfresco/core/Core",
        "vue"], 
        function(declare, _WidgetBase, _TemplatedMixin, template, AlfCore, Vue) {
   
   return declare([_WidgetBase, _TemplatedMixin, AlfCore], {

      templateString: template,

      postCreate: function vue_VueExample__postCreate() {
         new Vue({
            el: "#" + this.id,
            data: {
               message: "Hello Vue.js!"
            }
         });
      }
   });
});

 

The key things to notice here are that we're importing the "vue" package, and the "VueExample.html" template. You might also notice that the call to create a new Vue component uses a slightly different el attribute - in this case we're just using the id attribute that will be generated for us by Aikau (unless we explicitly provide one)... this is guaranteed to be unique to ensure that vue.js will only work with the right widget instance!

 

The template file is also very similar:

 

<div class="blog_VueExample">
  <p>{{ message }}</p>
</div>

 

...the only difference is that we're specifying a BEM style class for our widget. We use BEM throughout our Aikau widgets to ensure that styles do not "bleed" between widgets inadvertently.

 

Defining the Dashlet

I described in detail how to create an Aikau dashlet in this previous blog post so I won't dwell on it too much - this is the JavaScript controller for defining it:

 

model.jsonModel = {
   rootNodeId: args.htmlid,
   pubSubScope: instance.object.id,
   services: [],
   widgets: [
      {
         name: "alfresco/dashlets/Dashlet",
         config: {
            title: "vue.js example",
            bodyHeight: args.height || null,
            componentId: instance.object.id,
            widgetsForToolbar: [],
            widgetsForBody: [
               {
                  name: "blog/VueExample"
               }
            ]
         }
      }
   ]
};

 

The main thing to note is that the widgetsForBody is where we're placing our new vue.js Aikau widget.

 

The End Result

After building the extension JAR and dropping it into the share/WEB-INF/lib folder and restarting Share the dashlet is available to be added to dashboards and looks like this:

vuejs dashlet.png

 

Summary

OK.... so it's not the most exciting showcase of the capabilities of vue.js, but if you're interested in using vue.js in your Share customizations then using this approach is probably a good place to start. I'll read a bit more into vue.js and see if it's something that we can use more of in Aikau as it does seem like a good fit for providing enhanced templating and binding capabilities. I'd be interested to know people's thoughts on this - please let me know in the comments section if you've tried out vue.js and what you think of it.

 

You can find the source code for this example in this GitHub repository.

Outcomes