1

Suppose I have a JSON tree structure as follows:

var myTree = {
  "node": {
    "name": "A",
  },
  "children": [
    {
      "node": {
        "name": "B",
      },
      "children": []
    },
    {
      "node": {
        "name": "C",
      },
      "children": []
    }
  ]
}

This is just an example showing the structure of the tree. But in reality the tree might be much larger and it has an arbitrary (unknown) depth.

I want my angularJS app to display this as a set of nested <ul>s as follows:

<ul>
  <li>A
    <ul>
      <li>B</li>
      <li>C</li>
    </ul>
  </li>
</ul>

I don't care about the whitespace. All I really care about is that it appears as nested bullet points.

I have also created the following recursive function that converts the JSON into the correct HTML:

self.HTMLTree = function(jsonTree) {
  var retStr = '<li>' + jsonTree.node.name;
  if (('children' in jsonTree) && (jsonTree.children.length > 0)) {
    retStr += '<ul>';
    for (childIndex = 0; childIndex <= jsonTree.children.length - 1; childIndex++)
      retStr += self.HTMLTree(jsonTree.children[childIndex]);
    retStr += '</ul>';
  }
  retStr += '</li>';
  return retStr
}

In my HTML, I call it like this:

{{myCtrl.HTMLTree(myCtrl.myTree)}}

When I load this page, instead of seeing the bullets, I see the entire HTML returned by HTMLTree() rendered as text. Why? How do I make it render the actual bullets?

And is my way of constructing the HTML tree the right way to do it? It feels wrong. I feel like I should be able to somehow due it purely in the angular view file without coding HTML into my Javascript.

Here is the JSFiddle

Saqib Ali
  • 11,931
  • 41
  • 133
  • 272
  • Use `return $sce.trustAsHtml(retStr)`. Also remember to inject $sce into your controller. Ideally you would use a directive for this, see this [question](http://stackoverflow.com/questions/14430655/recursion-in-angular-directives) for more info. – Thomas Ghesquiere Feb 21 '16 at 10:59
  • Hmmm, @ThomasGhesquiere, I tried that here but it didn't seem to work: https://jsfiddle.net/qxhhvw7v/8/ – Saqib Ali Feb 21 '16 at 11:08
  • 1
    See Shashank's answer, `
      ` was the missing key. (your fiddle was also missing a return statement).
      – Thomas Ghesquiere Feb 21 '16 at 11:15

    1 Answers1

    1

    Try in this way and find the sample code here.

    HTML:

    <body ng-app="myApp">
        Hello World!
        <div ng-controller="MyController as myCtrl">
            <ul ng-bind-html="myCtrl.HTMLTree(myCtrl.myTree)"></ul>
        </div>
    </body>
    

    JS:

    myApp = angular.module('myApp', []);
    
    
    myApp.controller('MyController', function ($scope, $sce) {
        var self = this;
    
        self.myTree = {
            "category": {
                "name": "A",
            },
            "children": [{
                "category": {
                    "name": "B",
                },
                "children": []
            }, {
                "category": {
                    "name": "C",
                },
                "children": []
            }]
        }
    
        self.HTMLTree = function (jsonTree) {
            var retStr = '<li>' + jsonTree.category.name;
            if (('children' in jsonTree) && (jsonTree.children.length > 0)) {
                retStr += '<ul>';
                for (childIndex = 0; childIndex <= jsonTree.children.length - 1; childIndex++)
                    retStr += self.HTMLTree(jsonTree.children[childIndex]);
                retStr += '</ul>';
            }
            retStr += '</li>';
            return $sce.trustAsHtml(retStr);
        }
    });
    
    Shashank
    • 2,010
    • 2
    • 18
    • 38