handsome
handsome

Reputation: 2392

render HTML in angularJS 1.x

I have a directive and I´m replacing IMG urls with img src to display images inline

function message($filter) {

    var directive = {
        restrict: 'EA',

        scope: {
            data: '='
        },

        link: function(scope, elem, attrs) {
            scope.data.content = scope.data.content.replace(/(https?:\/\/\S+(\.png|\.jpeg|\.jpg|\.gif))/g, "<img src='$1' alt=''>");
        },

        template: '<span>{{data.nickname}}:</span> {{data.content}}'

    };

    return directive;
}

but instead of seeing the image inline I´m seeing the HTML tag as text I´m investigating $sce but I´m not sure how to use it inside a directive.

Upvotes: 3

Views: 1125

Answers (2)

frodo2975
frodo2975

Reputation: 11725

So, a more angular and safer way to do this is to not write html to the template directly. Instead, you can use curly brackets to put the image url in the template like this:

template: `
    <span>{{data.nickname}}:</span>
    <img ng-if="{{data.hasImage}}" src="{{data.url}}" alt="">
`

This preserves template/data separation.

The way you had it, you're putting yourself at risk of XSS. There's a reason angular makes you jump through hoops in order to put generated html in a template. If a user ever is able to upload an image with js in the url, your site could be hacked. Angular's normal templating prevents this kind of attack automatically.

If you need multiple images, you can put add a url property to each object in your data, put the data array on the scope, then use ng-repeat to render the array of objects.

Upvotes: 1

31piy
31piy

Reputation: 23849

You are closer!. You are right about working with ngSanitize module.

It basically allows you to write raw HTML in your template (using ng-bind-html directive). You need to include it in your page, and declare it as a dependency in your module like this:

<!-- HTML -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-sanitize/1.6.2/angular-sanitize.min.js"></script>

// JavaScript
angular.module("yourapp", ['ngSanitize']);

And then, bind your HTML content in a div (or whatever) using ng-bind-html directive like this:

template: '<span>{{data.nickname}}:</span> <div ng-bind-html="data.content"></div>'

Now, the raw HTML contents of data.content will be replaced as is in your directive's template. Here is a working plunker for your reference.

Upvotes: 8

Related Questions