Creating a visual representation of a JSON tree using nested <ul> elements in AngularJS

Consider a JSON tree structure like the one shown below:

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

This example represents the basic structure of a tree, which can be much larger and have an unknown depth in real scenarios.

The goal is to display this tree in an AngularJS app using nested <ul> elements as shown below:

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

The focus is on achieving the nested bullet point display rather than exact formatting.

To convert the JSON tree to the desired HTML structure, a recursive function is implemented as follows:

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
}

Invocation in the HTML template is done like this:

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

When the page is loaded, the HTML returned by HTMLTree() is displayed as text instead of rendered bullets. How can this be fixed?

Furthermore, is this approach of constructing the HTML tree considered optimal? It seems like there should be a way to accomplish this purely within the Angular view file without embedding HTML in the Javascript logic.

For a live example, check out the JSFiddle

Answer №1

Check out this approach and discover the example 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);
    }
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Switching between sockets on a rotational basis

Imagine there is a division in the HTML file, and an interesting game is being played where each player has the opportunity to change the color. However, there’s a twist – they can only switch colors after the other player has taken their turn. The pla ...

What is the technique for placing a div element directly within the href attribute in a shape

I am wondering if it is feasible to include the following divs <div id="cal1"> [dopbsp id="1" lang=it]</div> <div id="cal2"> [dopbsp id="1" lang=it]</div> <div id="cal3"> [dopbsp id="1" lang=it]</div> directly wit ...

What is the best way to assign string values from an array in data() to the src attribute of an image element?

I've been working on a feature where the <div.box> element appears based on the user's input through a form. In this project, I'm using vue3 and v-for to iterate over an array 'images' that contains URL strings linking to ima ...

Converting NSData into NSString: circumventing the NSLog restriction

My challenge lies in transforming NSData into NSString within Zendesk, but I am encountering an issue where the string remains incomplete or unable to decode the data entirely. Executing the following curl command yields the expected response displaying a ...

Covering the entire screen, the Div element takes up the entirety of

Just like with other pages, the main div always takes up the entire screen visible to the user. As they scroll down, another div becomes visible: example1 , example2 Regardless of the screen size, the main div will always fill the space visible to the use ...

Puppeteer Alert: Unable to Locate Node for specified selector

When using Puppeteer to interact with an input element on a requested URL, I encountered an issue. First, I entered a quantity like this: await page.type('#bidamount_temp', bidAmount); However, when trying to click on the following button after ...

Tips for refreshing information in the Angular front-end Grid system?

I am currently working with the Angular UI Grid. The HTML code snippet in my file looks like this. <div ui-grid="gridOptions"></div> In my controller, I have the following JavaScript code. $scope.values = [{ id: 0, name: 'Erik&a ...

When loading a page in NodeJS and Express, there are no initial displays, but upon refreshing the page, all data is successfully retrieved

Struggling to solve this issue that has been lingering for a while. I'm currently working on a project where a remote JSON file is loaded into memory, parsed, and the results are displayed on the page (using pug). Everything seems to be working fine ...

Plugin combination of Cordova File, InAppBrowser, and File Opener

I am experiencing an issue with opening a PDF file that I have stored using the File Plugin. I have tried using both the InAppBrowser and File Opener Plugin, but neither seem to work. I am currently using the Visual Studio Emulator KitKat for Android. Whe ...

Having issues with $emitting not working for parent-child components in Vue. Any ideas on what I might be doing incorrectly?

I have a login component that I need to call in the main vue component of App.vue. Within the login vue, when I click on any button, it should activate another vue component using Vue.js router to replace the login page. I have searched for solutions but h ...

What is the recommended way to include an image in a v-for loop in Vue.js?

I have attempted various online solutions, but I am still unable to display images on the screen. Could it be a simple mistake? The file names and folders are accurate. When providing the path, I aim to retrieve the image associated with the sub-club name ...

Supply a JSON parameter as a variable into the .load() function

When a button is clicked, I am attempting to load a page using the .load() method with a POST request. The URL parameters are generated and displayed as JSON formatted in the button attribute btn-url. Problem: The parameter is not being passed to the .loa ...

AngularJS is throwing an error because it can't find a function called 'undefined' in Controller xxx

Just diving into the world of Angular. I'm following an example from a reputable book, but encountering an issue with the Cart Controller not being recognized as a function. Here's the code snippet causing trouble: HTML: <!DOCTYPE html> & ...

PrimeFaces Issue with Redirection

Hello everyone, I am currently dealing with a redirection issue. Basically, I have an API that gets triggered when a user clicks on an image. This API captures the user's contact number and initiates a call through the software. Everything is functi ...

Issues with syntax in AJAX programming can be a significant road

I have a function linked to an onclick button event. This function sends data via ajax to another php file. Everything was working smoothly until I tried to add an IF statement to the 'success' section, which would receive true or false from an e ...

Incorporating external script into React website's functional component

I have invested countless hours on this particular issue, which appears to be quite trivial, yet I am unable to pinpoint where my mistake lies. I recently purchased terms and conditions from Termly.com and now wish to showcase these terms and conditions o ...

When a hard refresh is triggered, Vue's navigation guard takes precedence over localStorage

Currently, I am working on implementing a permission check for users before they can access a specific route. I have experimented with using both route.beforeEach and route.beforeResolve. Everything functions as expected if the localStorage within the tab ...

Lamenting the Perils of Losing AngularJS Rootscope Data upon Refresh

Currently, I am facing an issue in AngularJS 1.x. When I save a value in the $rootScope and pass to the next page or router, unfortunately, the $rootScope value gets lost upon refreshing the page (F5/Window Reload). I need a solution that doesn't inv ...

Appending a row to a table will not trigger events in Select2

Despite several attempts, I can't seem to get the select2:select event working on dynamically added rows in a table using select2. The event only works on the original row. Unfortunately, I don't have any additional details about this issue. COD ...

Is it possible to select options in AngularJS based on certain criteria?

I created an AngularJS select menu that is currently functioning correctly: <select name="s1" id="s1" multiple="multiple" data-native-menu="false" data-role="none" ng-model="userlistSelect" ng-options="u.userId as u.fi ...