Implementing your own JSF tabview component without Primefaces

At my current company we are finally transitioning away from our well-aged Primefaces 3.0 jsf library and have implemented our own (composite) components for all use cases where we used primefaces thus far. As I learned a few things while implementing the components, I thought I could share it with others as good tutorials for composite components are quite rare.

Our composite component which we will be developing here is a tabview component just like the one you see on this screenshot of primefaces showcase. The tabview needs to render 1-n different tabs which the user can switch through freely with a click to the tab header. It’s a standard widget found in every operating system and many widget frameworks.

We will develop it based on twitter bootstrap markup and you can use it without any additional client javascript, you don’t even need the bootstrap.js as the switching of tabs is entirely done on the server side (we are talkng about JSF here!). The main advantages of it over the primefaces tabview are that you have learned something about jsf and that you can freely change the html markup as you need it. You can use any CSS styling framework you like.

The component should work with every JSF 2.x version.

Download

You can download the complete source code in my tabview github repository. You have to copy the templates and classes to your project manually. Don’t forget to adjust the package name of the class and the component name inside the class. If you have any question or suggestion just leave a comment.

Continue reading Implementing your own JSF tabview component without Primefaces

Creating open source code is helping me as a developer

When creating the github project and transferring the code for jsf-updates-angular I realized that opening up my code to the public, is helping me being a developer.

While creating the company internal code that jsf-updates-angular is based on, it was done as a part of a bigger code base. It was only a small part in a test branch. I did not really pay attentention to implement it in the most clean way. I mean … it was not bad code. But it was embedded and not meant to be used as a standalone library. It used jQuery, naturally, because jQuery is part of this project. It was a part of an existing module which was easy because it was already there.

jsf-updates-angular (jua) does not really need jQuery. When I would try to, I could do the DOM work on my own. Currently, even the released version of jua is using jQuery. I would only need to ready some articles to make myself familiar with the original browser API to the DOM. That can’t be that hard.

Ripping the code out and releasing it as a standalone module already gave me a new look onto my code. I already have tweaked it and thought about how others will likely use it. The code is now better than before. I did not think about this while writing this code in my company because … no one will take the file and use it somewhere else. No need to optimize it. Its just there.

But while releasing it, I looked on my code with other eyes. Maybe I saw it like I was an external code reviewer. Maybe I saw it as I would see it when I was the customer.

My company will benefit when I release open source software, because I’m learning.

And the next version of jua will not need jQuery.

Datatable with fully dynamic columns in angularJS

First: there is a plunkr example for the following code examples.

While doing some testing for a possible new project which we want to do in angularJS I discovered that its quite hard to implement a datatable which should have fully dynamic columns which can be reordered and toggled to display or not.

Many datatable implementations have either hard-coded columns which you can’t change at all or you can’t change the order of the columns in which they should be rendered. ngTable does it like that for instance.

So, I spent a rainy sunday afternoon to implement my own version and after much poking around and some frustrating moments, I finally got it.

The first hurdle I had to take was, that angularJS can’t handle directives that have a <tr> or <td> element as the root element of the directive. There is an issue for this where its explained that these elements need to be handled special, which jQuery does, but jqLite in angularJS does not. There is a pull request for this too, but its not accepted yet.

After discovering that, I wrote a little helper function to create the elements like this:

function createTDElement() {
	var table = angular.element('<table><tr><td></td></tr></table>');
	return table.find('td');
}

The next problem I had was to implement the full dynamic columns which should be customizable from an angular controller. I didn’t want just define a hard-coded table with some columns in a html file and manipulate the DOM elements after they were created by angularJS. I wanted to do it the angular way.

I decided that every column needs to have its own directive where the output inside the cells is defined. These directives are not known to the wrapper directive, but are part of the customization inside the controller, so the wrapper is fully generalized and can be used with any type and any number of columns. The wrapper directive adds additional elements into the DOM in the $compile phase of angularJS which have the correct column directives set to them dynamically.

The html in the view looks like this:

<table border="1">
    <tr ng-repeat="item in items" item="item" columns="columns">
</table>

Inside the controller you have something like this:

function myController($scope) {
   $scope.items = [//someitems];

  $scope.columns = [{
    id: "column2",
    title: "Manufacturer",
    directive: "secondcolumn",
    visible: true
  }, {
    id: "column1",
    title: "ID",
    directive: "firstcolumn",
    visible: true
  }, {
    id: "column3",
    title: "Country",
    directive: "thirdcolumn",
    visible: false
  }, ];
}

So in this case the table should render with 2 columns: column2 first, then column1 and column3 should not be visible. The property “columnDirective” is used to find out the directive that renders this columns html output.

$scope.items is the data object, that you want to display in the table.

The important parts of the column directive, which does all the magic, look like this:

function createTDElement(directive) {
	var table = angular.element('<table><tr><td ' + directive + '></td></tr></table>');
	return table.find('td');
}
app.directive('item', function($compile) {
  function createTDElement(directive) {
    var table = angular.element('<table><tr><td ' + directive + '></td></tr></table>');
    return table.find('td');
  }

  function render(element, scope) {
    var column, html, i;
    for (i = 0; i < scope.columns.length; i++) {
      column = scope.columns[i];
      if (column.visible) {
        html = $compile(createTDElement(column.directive))(scope);
        element.append(html);
      }
    }

  }

  return {
    restrict: 'A',
    scope: {
      item: "=",
      columns: "="
    },
    controller: function($scope, $element) {
      $scope.$watch(function() {
        return $scope.columns;
      }, function(newvalue, oldvalue) {
        if (newvalue !== oldvalue) {
          $element.children().remove();
          render($element, $scope);
          $compile($element.contents())($scope);
        }
      }, true);
    },
    compile: function() {
      return function(scope, element) {
        render(element, scope);
      }

    }
  };

});

(The implementations for the columns are missing here).

And thats it.

I created a plunkr which has an working example for this so you can play around with it.

Tell me if you know some way to implement this easier.

How to handle angularJS promises in jasmine unit tests

When developing unit tests in an angularJS app, you eventually stumble about a problem that can be quite frustrating to handle it in a clean und concisive way: promises.

Lets have a look at an example method in a controller:

$scope.method = function() {
    someService.loadData().then(function(data) {
       $scope.data = data;
    }
}

This method is calling loadData() on an angularJS service which is returning a promise, which could be resolved only after a $http call is finished.

How to handle that in a unit test?

Clearly, you should mock someService, thats easy. But what to do with the promise? In my first couple of tests, I tried to reimplement promises somewhat and ended with ugly constructs like this:

someServiceMock = {
    loadData: jasmine.createSpy().andCallFake(function() {
        then: jasmine.createSpy()
    }
}

This way I had to call the resolve or reject functions in my test manually, like so:

it('should be a lot easier', function() {
   controllerScope.someMethod();

   resolveFunction = someServiceMock.loadData().then.mostRecentCall.args[0];
   resolveFunction('resolveData');

   expect(controllerScope.data).toBe('resolveData');
});

That worked, but its ugly as hell.

So, after some studying with google I just refactored my tests with a much simpler solution, which uses the original $q service to resolve promises and calls the appropriate function arguments automatically.

Defining the mock service changes a bit and needs to be in an inject function as $q service is needed:

beforeEach(function() {
    inject(function(_someService_, _$q_, _$rootScope) {
        var deferred = _$q_.defer();
    
        someService = _someService;
        rootScope = _$rootScope_;
    
        deferred.resolve('resolveData');
        spyOn(someService, 'loadData').andReturn(deferred.promise);
    })
})

it('is now a lot easier', function() {
   controllerScope.someMethod();
   rootScope.$apply();
   expect(controllerScope.data).toBe('resolveData');
}

The loadData() spy is now always returning a resolved promise.

Of course, you can (and maybe should be) resolve the promise in the test itself if the data is different when you have more than one test.

The catch is though, that you need to call rootScope.$apply() method manually in your test as promises only get resolved during a angular $digest phase. After this method is finished, all promises are really resolved and you can test for the expected outcome.

Mocking $window in an angularJS test

When trying to mock the angularJS internal $window factory, I recently stumbled about an error message when running the test:

TypeError: Cannot read property 'userAgent' of undefined
	    at $SnifferProvider.$get (C:/projects/hwa-mobile/src/main/external-libs/angular.js:8327:72)
	    at Object.invoke (C:/projects/hwa-mobile/src/main/external-libs/angular.js:2864:28)
	    at C:/projects/hwa-mobile/src/main/external-libs/angular.js:2702:37
	    at getService (C:/projects/hwa-mobile/src/main/external-libs/angular.js:2824:39)
	    at Object.invoke (C:/projects/hwa-mobile/src/main/external-libs/angular.js:2842:13)
	    at C:/projects/hwa-mobile/src/main/external-libs/angular.js:2702:37
	    at getService (C:/projects/hwa-mobile/src/main/external-libs/angular.js:2824:39)
	    at Object.invoke (C:/projects/hwa-mobile/src/main/external-libs/angular.js:2842:13)
	    at C:/projects/hwa-mobile/src/main/external-libs/angular.js:2702:37
	    at getService (C:/projects/hwa-mobile/src/main/external-libs/angular.js:2824:39)

The test looked something like this:

describe('myService', function () {
	beforeEach(function () {
		module("myModule",function ($provide) {
			$provide.factory('$window', function () {
				return jasmine.createSpy('$windowmock');
			});
		});
		....
	});

	it('should do something', function () {
		...
	});
});

Apparently angularJS itself tries to read the userAgent even when running inside a mocked environment.

The solution was quite easy:

describe('myService', function () {
	beforeEach(function () {
		module("myModule",function ($provide) {
			$provide.factory('$window', function () {
				var windowmock = jasmine.createSpy('$window);
				windowmock.navigator = window.navigator;
				return windowmock;
			});
		});
		....
	});

	it('should do something', function () {
		...
	});
});

The navigator property of the jasmine mock object will be the original navigator property of the original window object. Smells a bit, but works.

How to structure large angularJS applications

I did it all wrong in my first angularJS application. Oh I did it really wrong!

The structure of my first angular project looked something like this:

Root folder
js
controllers
Somecontroller.js
Anothercontroller.js
controller.js
directives
Firstdirective.js
SecondDirective.js
directives.js
services
AService.js
BService.js
services.js
app.js
index.html
partial1.html
partial2.html

So, all controllers were going to “controllers” folder, services into “services” folder and partials lived directly next to full html files. When we started to have more than 10 directives and 5 services the problems with this approach were really backfiring:

  • it was not easily visible what files were depending on what other files
  • refactorings were thus quite hard
  • reusing features in other code/applications was hard as the structure didn’t allow to group files of a single feature together
  • it was hard for new developers to understand the flow of the application
  • it was hard to extend the application so that it not only consisted of one (single page) application but of two applications that shared some features

Since then I tried a few different approaches and while experimenting with ngStart as a skeleton for new angular projects I’m now settled with an approach I want to use in all my next projects.

What I came up with, is an approach that groups features into angularJS modules. The main advantages is that the code structure is based on features of the application and every feature is defining its own angularJS module. The angular root module then is the glue and binds all modules together.

The structure of ngStart looks like this:

Root folder
modules
contact
contact.js
contact.html
ContactController.js
ContactService.js
about
about.js
about.html
AboutController.js
app.js
index.html

The main idea is that every folder under “modules” is by definition an angular module. The module is always declared in a javascript file that is named like the folder (“about” -> about.js) and is the name of the module too.

Each angular module can use the full list of angular features. It can have its own angular.config() phase function, can declare its own routes and can have its own list of dependencies.

modules

To refactor a certain feature you now know exactly where to begin and what files are directly dependent on each other when they implement a single feature. You can move modules around and even move them out of the your first single-page app, make another app and declare a dependency on the module to reuse your code.

In a small and trivial example the advantages of this approach are not easily visible, but as soon as a team of developers works together on an application it will grow very fast.

In enterprise applications there is usually a software architect who defines a structure which the team has to follow. Programming languages in the backend also have features to structure code in packages or modules and import it. Javascript doesn’t. And often times the software architect doesn’t care about javascript or the frontend at all. And frontend developers tend to not care about it neither as tools were missing in the past and there wasn’t really a need for it when writing jquery scripts.

But as frontend engineers or frontend developers of today, you should care! AngularJS is great. But angularJS applications will face the same problems as every other application that begins to grow. And your structure should make it easy to grow and adapt. You should care from the beginning!

unit-testing angularJS controllers in a non-trivial environment

I just released a new patch version of my angularJS sekeleton project ngStart. It now contains a sample unit test for a controller.

There are many examples out there how to unit test an angularJS controller. Basically you have to create a new controller scope yourself and tell angularJS to create a new scope instance for a given controller. This looks usually like this (as a jasmine test):

describe("the controller", function () {
	var contactController, scope;
	beforeEach(function () {
		inject(function ($rootScope, $controller) {
			scope = $rootScope.$new();
			contactController = $controller("contactController", {$scope: scope});
		});
	});

	it("should be something", function () {
		expect(scope.someProperty).toBeDefined();
	});
});

Note: this code assumes that the controller was registered in the production code via a call to angular.controller like this: angular.controller(“contactController”, function($scope){…}

The catches in my ngStart project are, that

  • its a requireJS environment and
  • that the controller is not registered by name as its usually done in simple projects, but the controller is defined inside a route definition without an explicit name. The controller is only valid for the given route. As far as I know, you can’t access it via a name anywhere outside.

The route definition looks like this:

define(['angular', 'ContactController'], function (angular, ContactController) {

	var contact = angular.module("contact", []);

	contact.config(["$routeProvider", function($routeProvider) {
		$routeProvider.when('/contact/', {
			templateUrl: 'contact.html',
			controller: ContactController
		});
	}]);

	return contact;
});

 

How do you test the controller now in a unit test if you can’t access it via name?

Easy.

As we can load the controller definition with requireJS (aka its function representation) you can give the $controller function this controller function directly. You don’t have to provide a string which angularJS uses to look for a registered function like its done with a call to angular.controller(“name”, controllerFunction).

The rest is the standard behaviour like above:

define(["contact/ContactController"], function(ContactController) {
	describe("the controller", function () {
		var contactController, scope;

		beforeEach(function () {
			inject(function ($rootScope, $controller) {
				scope = $rootScope.$new();
				contactController = $controller(ContactController, {$scope: scope});
			});
		});

		it("should be something", function () {
			expect(scope.someProperty).toBeDefined();
		});
	});
});

Frontend optimizations for HTML5 web apps

I did a presentation in front of some colleagues some time ago and it was then when I realized how successful our frontend optimizations really are.

Our mobile web app which is running with angularJS and jQuery Mobile is loading over 1.6MB in more than 50 HTTP requests in local development mode. Only the laziest developers would give THAT to their customers.

After all optimizations done during grunt build, customers need to load only 250kB in 13 HTTP requests on their first visit. Although the number of HTTP seems a bit high, this is a appcache app and it contains all ressources ever needed for the app, including HTML files and all images, fonts and styles.

Because of appcache caching a returning visitor needs to only load 3kB for the whole app in 1 HTTP request. Thats, right. 3 kB! Thats the initial payload for the JSON data that the app loads from a REST service.

3kB instead of 1.6MB. How is that possible?

Here is a list of most optimzations that is done during grunt build:

  • all javascript files are concatenated and optimized with requireJS optimizer into one single javscript file. This single steps is gaining by far the most in size and HTP requests as we structure our code in small and meaningful modules/files. Side effect: optimizer creates javascript source maps so debugging is possible even in minized code on production.
  • all css files are concatenated and optimized into one single css file
  • all images (icons) are written as base64 into the css file as data URIs. Though the images are around 20% bigger, the browser saves heavily on fewer HTTP request which outweighs the bigger data by far!
  • an appcache manifest file is created during build and referenced inside the HTML files. The browser can then load the whole app during first visit and needs only to load dynamic data on subsequent visits.

That is only a part of the build process. What I learned during developing this build system, was the foundation what I did later in my angularJS skeleton project: ngStart

Grunt is a fabulous build tool and there is already a plugin for most, if not all frontend optimizations. You only have to configure them.