How would I render html tags inserted via compile in AngularJS?

903 views Asked by At

I am creating a UI that would allow a user to create preview html content.

For the purposes of this question, lets say I have the following array of objects:

modules = [
    {
        id: 0,
        type: 'title',
        content: 'This is the title',
        subtitle: 'This is the subtitle'
    },
    {   
        id: 1,
        type: 'intro', 
        content: 'This is the <b>intro copy</b>. This is the intro copy!'
    },
    {   
        id: 2,
        type: 'title',
        content: 'This is the title'
    }
];

I have created a directive that loops through the objects to choose a template based on the type and uses $compile to render the different modules.

app.directive('module', function( $compile ){

    // Define templates as strings
    var titleTemplate = '<h1>' + 
                            '{{ module.content }}' + 
                        '</h1>' +
                        '<h3 ng-show="module.subtitle">{{ module.subtitle }}</h3>';

    var introTemplate = '<p>' +
                            '{{ module.content }}' +
                        '</p>' + 
                        '<p ng-show="module.secondContent"><em>{{ module.secondContent }}</em></p>';

    // Select the current template by value passed in through scope.module.type

    var getTemplate = function(moduleType) {

        var template = '';

        switch(moduleType) {
            case 'title':
                template = titleTemplate;
                break;
            case 'intro':
                template = introTemplate;
                break;
            case 'ribbon': 
                template = ribbonTemplate; 
        }

        return template;

    };

    // Pass the scope through to the template for access in the module

    var linker = function( scope, element, attrs ) {
        element.html( getTemplate( scope.module.type ) ).show();
        $compile( element.contents() )( scope );
        console.log(attrs);
    };

    return {
        restrict: 'E',
        link: linker,
        replace: true,
        scope: {
            module : '='
        }
    }
});

and finally, in the html I have

<module module="module" ng-repeat="module in modules"></module>

The issue that I have run into is that when I have an html element in the content, such as the <b>intro copy</b> in modules[1].content, the element is rendered as a string, instead of bolding the text like intended.

1

There are 1 answers

2
Okazari On BEST ANSWER

To interpret HTML from a var in angular you need to use the ng-bind-html directive. It will interpret the HTML instead of just showing it as a string.

Exemple :

$scope.myhtmlvar = "<b>I'm bold</b";

<div ng-bind-html="myhtmlvar"></div>

This looks good but will actually not work. Why ? For a good reason : interpreting HTML is not safe. Just imagine interpreting the whole html, the user can add as much javascript as he want and can completely inject his own behaviours and hack your application. To avoid this problem you will need to add the ngSanitize angular library into your project.

https://ajax.googleapis.com/ajax/libs/angularjs/X.Y.Z/angular-sanitize.js

And register it into your app

var app = angular.module('testApp', ['ngSanitize']);

From now your ng-bind-html will automatically sanitize the html you're giving him. The two lines ahead should now work.

Here is a working plunker as exemple

Hope it helped.