Compile Dynamic Html With AngularJS

With this tip I will show you how you can easily compile dynamic HTML so that it is bootstrapped to your AngularJS controller.

Recently I ran into an issue when I wanted rich tabular data, but also some handy AngularJS sexyness. Basically the tabular data was DB entries and I wanted to use Angular to bind the data of a specific entry to a single “edit” modal when that record was clicked. All seemed easy at the time, but with this project I decided to use Dynatable.

The problem is Dynatable tries to keep the DOM as lightweight as possible. Due to this it deletes and recreates the table rows as required while paging or searching. I prefer this approach over keeping the hundreds, perhaps even thousands, of rows on the DOM, and simply changing their display, but as a new record was created it was not bootstrapped to the Angular controller and the extra functionality provided by Angular was lost.

Now I will admit that I am still fairly new to AngularJS so there are probably better ways of doing this, but the solution I ended up going with is explained below:

I luckily, after hours of googling, ended up on an Angular documentation page regarding angular.injector. As per the documentation:

Creates an injector function that can be used for retrieving services as well as for dependency injection.

An example, which I borrowed from the documentation, can be seen below:

1
2
3
4
5
6
7
var $div = $('<div ng-controller="MyCtrl">{{content.label}}</div>');
$(document.body).append($div);

angular.element(document).injector().invoke(function($compile) {
  var scope = angular.element($div).scope();
  $compile($div)(scope);
});

Using the injector I was able to retrieve an instance of the $compile object. This combined with a handy dynatable:afterUpdate event hook provided by the authors of Dynatable I was able to easily compile the table rows as the user paged or searched through all the records. I have not noticed any performance impact yet and it works absolutely amazing.

This could be used with any DOM manipulating Javascript library/script, but as I mentioned there might be a better way that I don’t know of yet. One possibility might be a custom directive, but i’m way to new to Angular to be playing around with that.

If you are more experienced with Angular or know of any alternative, please feel free to correct me in the comments below.