Compiling dynamically inserted Angular Components

A pattern that comes up a lot in Angular is substituting an angular component into a string when it’s being rendered.

For example, replacing a user ID with a link to the user and avatar.

It’s only a few lines to do, but needs to be done in the directive at compile time.

.directive("foo", ['$compile', function($compile){
    return {
        templateUrl: "./components/foo/foo.html",
        controller: require('./components/foo/foo.js'),
        replace: true,
        restrict: "A",
        link: function(scope, element, attrs){
            if(scope.notification.data.title && scope.notification.data.title.indexOf("tagged-user") > -1){
                var compiledHtml = $compile(scope.notification.data.title)(scope);
                element.find(".post-body-inner-text").html(compiledHtml);
            }
            else{
                element.find(".post-body-inner-text").html(scope.notification.data.title);
            }
        }
    }
}])

Note the injection of $compile, which compiles the string and injects the new components.

Also note, the target container is

<span class="post-body-inner-text"></span>

(As referenced in the link function)

 

This *is* an unsafe injection angle, which is part of the reason you have to jump through some hoops. This notification data is sanitized server side before it hits our Angular app.

Published