Sulu tutorials

How to develop a bundle in the Sulu-Admin – #2: JavaScript

This part of the tutorial is based on the results of the previous blog-post.

The JavaScript part of Sulu might look a little scary on the first look but if you use our best practice to structure your files and our helpers & hooks you are able to build awesome UIs with less code!

Fundamentally the Sulu-Admin UI is build ontop of the library Husky which was built by MASSIVE ART. It uses AuraJS to bootstrap a "declarative component-based and event-driven RequireJS application". The complete Sulu-Admin application consists of loosely coupled AuraJS components. We have used AuraJS because of the small footprint and the extensibility.

All the bootstrap of your application is by the "SuluAdminBundle". It uses the "Admin" classes which we have defined in the last step of the tutorial to find the entry-point of your JavaScript components. Each Sulu bundle is able to extend the AuraJS application. E.g. you can extend the "sandbox" object which will be available in each component (this.sandbox). In this tutorial we will also see more usage of these extensions in Sulu.

"The JavaScript part of Sulu might look a little scary on the first look but if you use our best practice to structure your files and our helpers & hooks you are able to build awesome UIs with less code!"

Extension

To set the entry-point of the extension we return the Symfony bundle-short-name in the function "getJsBundleName" of the "NewsAdmin" class. This name follows the standards of Symfony by placing the public files ("Resources/public") into the "web/bundles/<shortbundlename>" folder.

// file: Admin/NewsAdmin.php

public function getJsBundleName()
{
    return 'examplenews';
}

To define the bundle-extension we have to add the file "Resources/public/js/main.js". This extension configures routes, paths and the directory to the components.

The following content initializes basic require paths, the component directory and the route that we have configured in the navigation https://github.com/sulu-io/ExampleNewsBundle/pull/1/files#diff-656b9372aac1b41132a33f5460c065a8R21.

// file: Resources/public/js/main.js

require.config({
    paths: {
        examplenews: '../../examplenews/js',
        examplenewscss: '../../examplenews/css'
    }
});

define(function() {
    
    'use strict';

    return {

        name: "Example News Bundle",

        initialize: function(app) {

            app.components.addSource('examplenews', '/bundles/examplenews/js/components');

            app.sandbox.mvc.routes.push({
                route: 'example/news',
                callback: function() {
                    return '<p>Hello awesome Sulu world!</p>'
                }
            });
        }
    };
});

After clearing the cache and install the newly created assets you should be able to click on the navigation link to see the content "Hello awesome Sulu world!"

app/console cache:clear && app/console assets:install --symlink --relative

First component

A basic component is a small RequireJS module that returns a constructor. The entry-point of the component is the initialize function. With this function you will be able to freely define the structure of your component. Here we will use a best-practice method which is currently standard in new Sulu components.

Read the documentation of components here.

define(function() {
    return {
        initialize: function() {
        }
    };
});

By initializing a component with different starting conditions the parent component is able to commit options ("this.options") into the component. The event system makes it possible to communicate with other components ("this.sandbox.on" and "this.sandbox.emit").

If you want more infomation about communication between components check out the AuraJS documentation.

For the last step in this tutorial we will extract the HTML content of our root into a dedicated component. (In one of the next parts of the tutorial we will explain the code to show a list of “News” articles.)

We have defined the directory for our components in the bundle-extension ("/bundles/examplenews/js/components"). Each component consists of one directory with multiple files (templates and javascripts). The main file of the component is the "main.js".

For our first component we use a very simple code-snippet which displays the message "Hello awesome Sulu world!". Therefor we have to create a file named "main.js" in the folder "Resources/public/js/components/news/list" with this code:

// file: Resources/public/js/components/news/list/main.js

define(function() {

    'use strict';

    return {
        initialize: function() {
            this.$el.html('<h1>Hello awesome ' + this.options.name + ' world</h1>');
        }
    };
});

In line with the AuraJS documentation we start this component ("news/list@examplenews") in the "example/news" route using markup to define the component and its options (look here).

// file: Resources/public/js/main.js

app.sandbox.mvc.routes.push({
    route: 'example/news',
    callback: function() {
		return '<div data-aura-component="news/list@examplenews" data-aura-name="sulu" />';
    }
});

That's it for the second part of the series. Next time we will introduce the Rest-API to fill our application with data.

The code for this part of the tutorial can be found here https://github.com/sulu-io/ExampleNewsBundle/pull/2.