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

3
  • Use return $sce.trustAsHtml(retStr). Also remember to inject $sce into your controller. Ideally you would use a directive for this, see this question for more info. Commented Feb 21, 2016 at 10:59
  • Hmmm, @ThomasGhesquiere, I tried that here but it didn't seem to work: jsfiddle.net/qxhhvw7v/8 Commented Feb 21, 2016 at 11:08
  • 1
    See Shashank's answer, <ul ng-bind-html="myCtrl.HTMLTree(myCtrl.myTree)"></ul> was the missing key. (your fiddle was also missing a return statement). Commented Feb 21, 2016 at 11:15

1 Answer 1

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);
    }
});
Sign up to request clarification or add additional context in comments.

Comments

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.