AngularJS, jQuery Plugins and UI.Utils

In a previous post, I wrote about using a Bootstrap 3 Admin theme to update the "look and feel" of the client application produced by the AngularJS Full-Stack generator.

In this post, we'll do some more refactoring in order to get the themes jQuery plugins to play nicely with AngularJS.

JQuery plugins

After theming your AngularJS client you may have noticed that the jQuery plugins are not responding to events. We can address this issue by leveraging the UI.Utils AngularJS module.

The UI.Utils module

The UI.Uitls module (refered to by its developers as the "Swiss-Army-Knife of AngularJS tools") includes a JQuery Passthrough directive and an Event Binder directive.

Use Bower to install the UI.Utils module:

bower install --save angular-ui-utils

Bower will copy the modules files into your project's bower_components folder, along with any dependencies.

Refactor index.html

Add the UI.Utils script to your project's index.html:

Refactor app.js

Add the UI.Utils module to your dependencies:

angular.module(myApp', [
  'ngRoute',
  'ui.utils'
])

The jsTree jQuery plugin

The Admin theme I chose uses the jsTree jQuery plugin:

We can config jsTree in app.js as follows:

angular.module(myApp', [
  'ngRoute',
  'ui.utils'
])
  .value('uiJqConfig', {
    jstree: {
      types: {
        default : {
          icon : 'fa fa-folder icon-state-warning icon-lg'
        },
        file : {
          icon : 'fa fa-file icon-state-warning icon-lg'
        }
      },
      "plugins": ["types"]
    }
  })

Refactor main.html

We need to add the JQuery Passthrough directive: ui-jq and the Event Binder directive: ui-event to the jsTree container:

<div id="jstree-document-browser" ui-jq="jstree"
 ui-event="{'select_node.jstree' : 'ctrl.selectNode($event)'}">

Refactor main.controller.js

Now, the select_node.jstree event will be passed to the selectNode function:

angular.module('webCaptureApp')
  .controller('MainCtrl', ['$log', function($log) {

    var self = this;

    self.selectNode = function(event) {

      var elementId = angular.element('#jstree-document-browser')
                        .jstree('get_selected')[0];
      var elementText = angular.element('#' + elementId).text();
      $log.info(JSON.stringify(elementText, null, 4));
    }

  }]);

We also need to update main.js to use the controllerAs sytax:

angular.module('webCaptureApp')
  .config(function ($routeProvider) {
    $routeProvider
      .when('/', {
      templateUrl: 'app/main/main.html',
      controller: 'MainCtrl as ctrl'
    });
  });