Home > Software Development > How to Create Plugin Framework Using AngularJS

How to Create Plugin Framework Using AngularJS

February 22nd, 2016 Leave a comment Go to comments

As I mentioned earlier, the AngularJS is an amazing JavaScript framework. It separates the model from view, and really makes programming in JavaScript pleasant. We actually use it in our recently released product DoubleCloud vSearch. I have personally used it for almost one year now and like it a lot even though I am not yet an expert.

While our product getting more complex over time, we are thinking to design an application framework so that we can have new modules plugged in easily. Think about the Eclipse plugin architecture has done for the IDE and RCP.

Lost VMs or Containers? Too Many Consoles? Too Slow GUI? Time to learn how to "Google" and manage your VMware and clouds in a fast and secure HTML5 App.

When searching the Internet, I found a few frameworks there already that are really powerful in their respective domains. When I tried to understand how it works under the hood, however, I found it’s too difficult and too long for me to digest.

Then, I came across a reasonably short sample as described in this blog post. Really a nice reading!

Inspired by the sample, I created the following concise sample just enough to show how a plugin system works. To make it easy to run, I simply include everything into one HTML file. In real project, you rarely see that. It’s better to have separate JavaScript files and include them in the HTML. In our case, there should be two JavaScript files, each of which corresponds to a module.

Anyway, let me explain a little how it works. In the HTML page, we had DempApp module as ng-app so that AngularJS knows to load that module. The DemoApp module declaration line in later script declares the dependency on the “framework” module and causes it to load as well.

Now, let’s take a look at the line “.” The any-list is alias for directive “anyList” in the “framework” module and causes the link function to run. It first tokenizes the plugin string for an array of plugin names. Then for each of the name, it creates a new directive line like ““. This is of course not what we want to have. That line must be further processed with the new directive expanded just like the “any-list”. Here is where the $compile service comes to help. It further triggers the “one” directive for its content.

All plugin’s contents are then pulled together into an ol element and added into the DOM element as a whole. Now you can see the following HTML code.

<any-list plugin="one,two,two,one" class="ng-isolate-scope">
  <ol>
    <li><one class="ng-scope"><b>I am one</b></one></li>
    <li><two class="ng-scope"><i>I am two</i></two></li>
    <li><two class="ng-scope"><i>I am two</i></two></li>
    <li><one class="ng-scope"><b>I am one</b></one></li>
  </ol>
</any-list>

With that being explained, let’s look at the big piture. The framework module takes care of the list structure. Each plugin decides its own content without the knowledge of the framework. Thus you can add new plugins with full control over the contents.

Although this is a very simple sample, it shows the basics of how an application framework can be built. Hope it helps for engineers who want to build plugin framework for large application.

<!DOCTYPE html>
<html>
  <head>
    <title>Framework Demo</title>
  </head>
  <body>
 
    <div ng-app='DemoApp'>
      <div ng-controller='MainCtrl'>
        Demo of Extensible Framework with plugins!
        <any-list plugin='{{plugin}}'></any-list>
      </div>
    </div>
 
    <script src="angular.min.js"></script>
    <script>
      angular.module('DemoApp', ['framework'])
        .controller('MainCtrl', function ($scope) {
          $scope.plugin = 'one,two,two,one';
        })
        .directive('one', function () {
          return {
            restrict: 'E',
            template: '<b>I am one</b>'
          };
        })
        .directive('two', function () {
          return {
            restrict: 'E',
            template: '<i>I am two</i>'
          };
        });
 
      angular.module('framework', [])
        .directive('anyList', ['$compile', function ($compile) {
          return {
            restrict: 'E',
            scope: {'plugin': '@'},
            link: function (scope, element) {
 
              var names = scope.plugin.split(',');
              var listE = angular.element('<ol>');
              element.append(listE);
 
              for (var i = 0; i < names.length; i++) {
                var template = '<' + names[i] + ' />';
                var compiled = $compile(template)(scope);
                var liE = angular.element("<li>");
                listE.append(liE);
                liE.append(compiled);
              }
            }
          };
        }]);
    </script>
  </body>
</html>
  1. No comments yet.
  1. No trackbacks yet.