0

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).

Serge van den Oever
  • 3,982
  • 7
  • 40
  • 63

1 Answers1

2

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.

Community
  • 1
  • 1
Ilan Frumer
  • 30,543
  • 7
  • 65
  • 81
  • Hi Ilan, great you found the issue. But the crazy thing is that if the tag is self-closing as in `
    ` it dies NOT work, but when it is written as `
    ` it works....
    – Serge van den Oever Feb 04 '14 at 13:59
  • Self closing div in html5 means
    , not
    : http://stackoverflow.com/questions/3558119/are-self-closing-tags-valid-in-html5
    – Paddy Feb 04 '14 at 14:29
  • @Paddy This is a self closing tag: `
    ` , have you even read the answer?
    – Ilan Frumer Feb 04 '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 04 '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 04 '14 at 15:06
  • Self-closing tags are also an issue in AngularJS. See: http://stackoverflow.com/a/25012451/476786 – bPratik Jul 29 '14 at 10:02