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

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

6 Comments

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....
Self closing div in html5 means <div>, not <div></div>: stackoverflow.com/questions/3558119/…
@Paddy This is a self closing tag: <div /> , have you even read the answer?
@Illan Frumer - your edit wasn't present when i commented. Was intended as a response to the OP anyway.
@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.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.