Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

What I know is when I want to insert HTML into view, I use 'ng-bind-html' or 'ng-bind-html-unsafe'.

What I don't know, is how to insert HTML and make Angular parse its content

i.e. if there is 'ng-repeat', I want Angular to parse it?

Update 1:

example:

HTML:

<div ng-repeat="t in ts" ng-bind-html-unsafe="t.html()"></div>

JS:

function Controller($scope) {
    $scope.ts = {obj1: new obj(), obj2: new obj(), ob3: new obj()};

}

function obj() {
    // which may be "<div ng-repeat="s in somthing">{{s}}</div>"
    // or "<ul><li ng-repeat="s in somthing">{{s.k}}</li></ul>"
    // or something else
    var _html;

    this.html = function() {
        return _html;
    }
}

I tried using the above, but Angular just print {{s}} or {{s.k}} as it is.

share|improve this question
add comment

3 Answers

up vote 2 down vote accepted

You can compile arbitrary HTML into an angular view with the $compile service (docs).

app.run(function($rootScope, $compile, $rootElement) {
  // We'll create a new scope to use as the context for the view.
  $scope = $rootScope.$new();
  $scope.model = [{name: 'first'}, {name: 'second'}, {name: 'third'}];

  // Calling `$compile(html)` returns a function that, when called with
  // a context object, links the compiled HTML to the given context (e.g.
  // binds scope-based expressions in the view to the passed in scope).
  var html = "<div ng-repeat='m in model'>{{m.name}}</div>";
  var linkingFunction = $compile(html);
  var elem = linkingFunction($scope);

  // You can then use the DOM element like normal.
  $rootElement.append(elem);
});

In this case, I've attached the view to the $rootElement (which is the element that was used when bootstrapping the module, usually by the ng-app directive); in many cases, you'll do this kind of thing in a directive's linking function and will have access to the element in question. You can, of course, get the raw HTML using jQuery or jqLite, but remember to allow at least one digest cycle on the linked scope before you do so (or else the HTML won't yet have been updated with values from the scope).

Working example: http://jsfiddle.net/BinaryMuse/QHhVR/

Down in the bowels of the ng-include directive, Angular's doing this very thing:

$compile(currentElement.contents())(currentScope);

[Update]

Here is a more complete example that demonstrates something a bit closer to your updated question:

app.controller("MainController", function($scope) {
  $scope.ts = [
    {
      elements: ['one', 'two', 'three'],
      html: '<div ng-repeat="elem in t.elements">{{elem}}</div>'
    },
    {
      things: [8, 9, 10],
      add: function(target) {
        var last = target[target.length - 1];
        target.push(last + 1);
      },
      html: '<ul><li ng-repeat="num in t.things">{{num}}</li>' +
        '<li><button ng-click="t.add(t.things)">More</button></li></ul>'
    }
  ];
});

app.directive("bindCompiledHtml", function($compile, $timeout) {
  return {
    template: '<div></div>',
    scope: {
      rawHtml: '=bindCompiledHtml'
    },
    link: function(scope, elem, attrs) {
      scope.$watch('rawHtml', function(value) {
        if (!value) return;
        // we want to use the scope OUTSIDE of this directive
        // (which itself is an isolate scope).
        var newElem = $compile(value)(scope.$parent);
        elem.contents().remove();
        elem.append(newElem);
      });
    }
  };
});
<div ng-controller="MainController">
  <div ng-repeat="t in ts" bind-compiled-html="t.html"></div>
</div>

Working example: http://jsfiddle.net/BinaryMuse/VUYCG/

It's worth nothing that the HTML snippets use t.elements and t.things because t is the scope value that is created by the ng-repeat in the outer HTML. You could do some scope gymnastics to make this a bit nicer if you like.

share|improve this answer
add comment

If you have a finite number of options for the elements in the repeat, you could use ng-switch instead or ng-include if the HTML is from the server.

share|improve this answer
 
But I don't want to include HTML, I just want to embed and parse HTML into another tag –  Ayman Sep 9 at 3:14
 
ng-include "fetches, compiles and includes an external HTML fragment", which causes all expressions, directives, etc. to be evaluated on the scope where the ng-include is used. –  Brandon Tilley Sep 9 at 3:26
add comment

Something like this?

<div ng-repeat="item in items">
    <div ng-bind-html-unsafe="item.html"></div>
</div>

where

items = [
    {
        html: 'test<br/>test'
    },
    {
        html: 'test2<br/>test2'
    }
]
share|improve this answer
 
close, the html will hold something like '<div ng-repeat="m in model">{{m.name}}</div>' –  Ayman Sep 9 at 3:16
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.