Appending complex markup with an Angular directive

Just a quick note in case anyone else runs into this issue.

A little while ago @iaintdoingit and I were working on an Angular form and were running into some trouble appending complicated content to elements on the page without affecting any other DOM structures (eg. extra wrapping). This is the combination of parsing, appending, not transcluding and compiling that finally brought it all together. It's not too complicated, but it took us longer than it should have to get it right.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
var myApp = angular
    .module("myApp", [])
    .directive('exampleAppendLabel', ['$compile', function ($compile) {
        return {
            link: function (scope, element, attrs) {
                var template = "<label for='{{field}}'>{{details.text}}</label>";
                var content = angular.element(template);

                element.after(content);
                scope.field = attrs.name;
                scope.details = angular.fromJson(attrs['exampleAppendLabel']);
                $compile(content)(scope);
            },
            scope: true
        };
    }]);

Which will work with the following markup.

1
2
3
4
5
6
7
8
<div ng-app='myApp'>
    <input 
        name='Name' 
        type='text' 
        example-append-label='{ "text": "Inserted Label Text" }' />
    <br />
    <button>Go</button>
</div>

This is a pretty simple example, but with access to anything you want in the data tags, and .parent() navigation on the element, it's possible to do some fairly complex stuff here.

This is also available as a jsfiddle. I hope it helps someone out.


comments powered by Disqus