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.

See plunker http://plnkr.co/edit/O3NSb2VEwAEDrkmtoKZ6?p=preview (version 15).

I have a simple example using ng-include to render a hierarchical template. It worls correctly if jQuery is included. Otherwise: it only renders the text of the chapter. If the rendering of the chapter text is commented out it correctly renders the text of the paragraphs. It looks like a bug in the AngularJS JQLite implementation, I think in the "after" function with implementation:

after: function(element, newElement) {
   var index = element, parent = element.parentNode;
   forEach(new JQLite(newElement), function(node){
      parent.insertBefore(node, index.nextSibling);
      index = node;
   });
}

Because I get the error: TypeError: Cannot call method 'insertBefore' of null.

My code as can be found in the above mentioned plunker is as follows:

index.html:

<!DOCTYPE html>
<html ng-app="plunker">
<head>
  <meta charset="utf-8" />
  <title>AngularJS template issue</title>
  <!-- uncomment line below to get it workinG using jQuery -->
  <!-- <script src="//code.jquery.com/jquery-1.10.2.min.js"></script> -->
  <script src="//code.angularjs.org/1.2.10/angular.js"></script>
  <script src="app.js"></script>
</head>

<body ng-controller="MainCtrl">
  <div ng-include="'template.html'"/>
</body>
</html>

app.js:

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

var lorumIpsumText = "<p>Lorem ipsum:<ul><li>one</li><li>two</li><li>three</li></ul></p>";

var chaptercontent = { 
  "Id":"SampleId1","Title":"1. Sample chapter one","Content":"<p>Text of sample chapter one<ul><li>one</li><li>two</li></ul></p>",
      "Paragraphs":[
          {"Id":"SampleId1.1", "Title":"1.1 First sample paragraph", "Content":lorumIpsumText, "Paragraphs":[]},
          {"Id":"SampleId1.2", "Title":"1.2 Second sample paragraph", "Content":lorumIpsumText, "Paragraphs":[]},
      ]
};

app.controller('MainCtrl', function($scope, $sce) {
  $scope.trustAsHtml = function(html) { return $sce.trustAsHtml(html); };
  $scope.chaptercontent = chaptercontent;
});

template.html:

<script id="paragraphTmpl.html" type="text/ng-template">
    <h4>{{paragraph.Title}}</h4>
    <!-- comment line below to have the paragraphs render correctly --> 
    <div ng-bind-html="trustAsHtml(paragraph.Content)"/>
    <ng-include ng-repeat="paragraph in paragraph.Paragraphs" 
                src="'paragraphTmpl.html'">
</script>

<div>
    <h3>{{chaptercontent.Title}}</h3>

    <div ng-bind-html="trustAsHtml(chaptercontent.Content)"/>
    <ng-include ng-repeat="paragraph in chaptercontent.Paragraphs" 
                src="'paragraphTmpl.html'"/>
</div>

Any advise on getting this to work without jQuery is much appreciated.

EDIT: Thanks to Ilan the issue is solved by not using a self-closing <div ng-bind-html='...'/>, but by writing it as <div ng-bind-html='...'></div>. I don't understand why, but jQuery seems to solve this case. See http://plnkr.co/edit/O3NSb2VEwAEDrkmtoKZ6?p=preview version 17 for the correct results).

share|improve this question

1 Answer 1

up vote 1 down vote accepted

After a short debugging, I found the bug is with your template:

You forget to close this div with </div>:

<div ng-bind-html="trustAsHtml(paragraph.Content)"></div> 

This mistake makes element.parentNode to be null:

after: function(element, newElement) {
   var index = element, parent = element.parentNode; // null

The implementation of jQuery is a little different but that's not a bug with jqLite.


self-closing div tags ( <div/> ) ?

HTML 5 doesn't support self-closing div tags.

Check this question: Is it valid HTML5 to use a single tag for a div?

XHTML ( which I definitely don't care about ) supports self-closing tags for all elements.

See What are all the valid self-closing elements in XHTML (as implemented by the major browsers)?

Your code is not compliant with XHTML anyway.

share|improve this answer
    
Hi Ilan, great you found the issue. But the crazy thing is that if the tag is self-closing as in <div ng-bind-html="trustAsHtml(paragraph.Content)"/> it dies NOT work, but when it is written as <div ng-bind-html="trustAsHtml(paragraph.Content)"></div> it works.... –  Serge van den Oever Feb 4 '14 at 13:59
    
Self closing div in html5 means <div>, not <div></div>: stackoverflow.com/questions/3558119/… –  Paddy Feb 4 '14 at 14:29
    
@Paddy This is a self closing tag: <div /> , have you even read the answer? –  Ilan Frumer Feb 4 '14 at 14:33
1  
@Illan Frumer - your edit wasn't present when i commented. Was intended as a response to the OP anyway. –  Paddy Feb 4 '14 at 15:01
    
@Ilan: thanks for enhancing your initial answer. Never knew that self-closing tags are not supported in Html5. Still strange that jQuery is smart enough to "solve" these kind of "errors"... maybe it is too smart. –  Serge van den Oever Feb 4 '14 at 15:06

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.