AngularJS template rendering using recursion concept

I'm having trouble getting this to work properly. I've simplified everything and put it in a fiddle: http://jsfiddle.net/svdoever/94aQH/1/.

My goal is to display a hierarchical chapter of a book that contains paragraphs, with the possibility for paragraphs to contain sub-paragraphs.

Here's the code snippet:

angular.module("myApp", []).controller("TreeController", ['$scope', function($scope) {
$scope.vm = {};
$scope.vm.chapter = {
        "Id": "N7313",
        "Title": "1 Chapter1",
        "Content": "<p>Contents1</p>",
        "Paragraphs": [
            {
                "Id": "N1.1",
                "Title": "1.1 Paragraph1.1",
                "Content": "<p>Content2</p>",
                "Paragraphs": [
                    {
                        "Id": "N1.1.1",
                        "Title": "1.1.1 Paragraph1.1.1",
                        "Content": "<p>ContentA</p>",
                        "Paragraphs": []
                    },
                    {
                        "Id": "N1.1.2",
                        "Title": "1.1.2 Paragraph1.1.2",
                        "Content": "<p>ContentB.</p>",
                        "Paragraphs": []
                    }
                ]
            },
            {
                "Id": "N1.2",
                "Title": "1.2 Paragraph1.2",
                "Content": "<p>Content3.</p>",
                "Paragraphs": []
            }
        ]
    };
}]);

Here's the corresponding HTML:

<div ng-app="Application" ng-controller="TreeController">
  <script id="paragraphTmpl.html" type="text/ng-template">
    <a class="anchor" ng-attr-id="data.Id"></a>
    <h4 ng-bind="data.Title" />
    <div class="paragraph-text" ng-bind-html="data.Content"></div>
    <!-- Want to remove the div from the repeat as well -->
    <div ng-repeat="paragraph in data.Paragraphs" ng-include="paragraphTmpl.html"></div>
  </script>

  <div class="bookchapter">
    <a class="anchor" ng-attr-id="vm.chapter.Id"></a>
    <h3 ng-bind="vm.chapter.Title" />
    <div class="chapter-text" ng-bind-html="vm.chapter.Content"/>
    <div ng-repeat="paragraph in vm.chapter.Paragraphs" ng-include="paragraphTmpl.html"/>
  </div>
</div>

I'm struggling to prevent a div from being rendered in the repeat loop as indicated in the comment. I know how to achieve this in knockout.js but haven't found a solution for AngularJS yet.

Any help would be greatly appreciated.

Answer №1

When dealing with recursion in child scopes of arbitrary size, it is essential to consider how to ensure that the 'data' variable can refer to different objects while sharing the same parent element.

To tackle this challenge, there are two potential approaches: one option is to develop a custom directive with a 'compile' function (although this may require some unfamiliar territory), and another option is to set a maximum depth of recursion by utilizing 'ngIf' to dynamically remove unused 'div' elements, which can be seen in the provided Plnkr example. For further insights, you can refer to this helpful question on Stack Overflow. Additionally, delving into Angular's directives documentation can provide valuable guidance if needed.

The code has been enhanced to address various concerns, however, eliminating the surplus 'div' elements remains a pending task.

You can explore the modified code here: http://plnkr.co/edit/ONnvYj91HRSvboWUxDg2

<div ng-app="Application" ng-controller="TreeController">
  <script id="paragraphTmpl.html" type="text/ng-template">
    <a class="anchor" ng-attr-id="data.Id"></a>
    <h4 ng-bind="data.Title"></h4>
    <div class="paragraph-text" ng-bind-html="data.Content"></div>
    <!-- The intention is to eliminate the div within the repeat loop as well -->
    <ng-include
      ng-if="data.Paragraphs.length > 0" 
      onload="data = paragraph" 
      ng-repeat="paragraph in data.Paragraphs" 
      src="'paragraphTmpl.html'"></div>
  </script>

  <div class="bookchapter">
    <a class="anchor" ng-attr-id="vm.chapter.Id"></a>
    <h3 ng-bind="vm.chapter.Title"></h3>
    <div class="chapter-text" ng-bind-html="vm.chapter.Content"></div>
    <ng-include  
      ng-repeat="paragraph in vm.chapter.Paragraphs" 
      ng-if="vm.chapter.Paragraphs.length > 0"
      src="'paragraphTmpl.html'" 
      onload="data = paragraph"/>
  </div>
</div>

Answer №2

This code snippet almost accomplishes your goal here

The crucial element you were missing is using single quotes around the template source name in ng-include. This distinction is important because without the quotes, it tries to find a reference to a scope variable.

<ng-include src="mysrc"></ng-include>
- attempting to access $scope.mysrc

<ng-include src="'mysrc'"></ng-include>
- searching for a template named 'mysrc'

The only limitation is that it does not remove the ng-repeat <div>, which may not be easily achievable.

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

Encountering a problem in a NextJS application where an error occurs stating "cannot read property of undefined (reading setState)" within

In an attempt to resolve the issue, I have linked the method to this inside the constructor. Additionally, I have utilized the arrow function technique to address the problem at hand. Despite these efforts, I continue to encounter the following error: Unha ...

The start screen fails to display when clicking the restart button

I am struggling to get the restart button to display the start screen again. Even though I have called the restart function within the clearColors function, which should show the start screen, it hasn't been effective so far. Initially, in the fadeOut ...

Unable to execute npm run command

I am working on a ReactJS project and have a package.json file that includes various dependencies: { "name": "front-end", "version": "0.1.0", "private": true, "dependencies": { "@ ...

Does Ajax XMLHttpRequest trigger the execution of servlet doFilter?

I've implemented an AJAX call from a JSP page as shown below: <head> <script> function loadXMLDoc() { var xmlhttp; if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, ...

Facing a problem with the Angular Factory service where an unknown provider is causing

I recently used a generator to set up my Angular project, but I encountered some issues with the formatting and distribution of code. As a result, I'm in the process of adapting my old project to fit the new structure so that my scripts deploy correct ...

What is the best way to import data into an Angular component version 1.5?

I have successfully implemented a basic component, but I'm encountering an issue when trying to load data via $http (users.get()) which returns a promise. While I can see the data in console.log(this.data), it's not getting rendered in the compon ...

Guide to removing an element without a specific parent reference

I need to remove list items that do not have a parent of ul This is the HTML snippet provided: <div class="yamm-content"> <div class="row"> <li> <a href="#">Should be deleted</a> </li> < ...

error when trying to bind attributes to knockout components

I am trying to dynamically add an id attribute to a tag, but it keeps giving me an error. "Uncaught ReferenceError: Unable to process binding "attr: function (){return {id:id} }" Message: id is not defined" Here is my HTML code- <label data-bind= ...

Having trouble retrieving base64 image data from a textarea upon submitting the form for the second time through ajax

My issue involves receiving image data in base64 format from a hidden textarea and saving that value through an AJAX call. The first time I submit the form using AJAX, an image is generated and a new image URL is displayed on success. However, when I try t ...

What is the root property in an NPM package.json file?

Is there a way in the package.json file to define the starting point for module resolution? For instance, imagine we have an installation in node_modules/mypackage/src/file1. All the files we need to import are located under the src directory. Is it possi ...

JavaScript array push is not functioning as expected

Having trouble getting my push function to work properly.. Here is my code snippet: var result = {}; dpd.timesheetsdone.get(function (timesheets, err) { if(err) return console.log(err); timesheets.forEach(function(entry, index) { result[ent ...

"I'm experiencing an issue where my JSON data is not displaying in the browser when I run the code

I am having trouble displaying my json data in the browser. This is my first time working with json and I can't seem to identify the issue. I tried researching online and found that it could be related to mime types, but I still can't solve it. B ...

Error encountered in AngularJs where the scope is not defined when binding a textbox

Attempting to link data from scope to input control using the code below. var app = angular.module('ng_app', []); app.controller("ITEM_Ctrl", function ($scope, $http) { var PlantId = "abcFC"; $scope.mdItemId; $scope.mdFlavorId; $scope.itemD ...

Searching for instances of code patterns in Node.js using regular expressions

I am working with a regex pattern that looks like this... /user/([A-Za-z0-9]*) When applied to the input string below, it produces the following result in console... ['/user/me', 'me', index: 0, input: '/user/me'] Here is ...

creating a spherical image mapping with three.js

I am currently facing a challenge in UV mapping a cube-map texture onto a sphere. The process of mapping a cube-map onto a cube was straightforward for me. I successfully mapped an image onto a cube using the following steps: Click here to open the image ...

Learning to implement $first in an Angular ng-repeat to dynamically add a new table row

I am currently facing an issue with displaying a Google map for addresses in my Angular application. The problem seems to be related to the asynchronous nature of HTML and JS, but I am struggling to find a solution. The issue is that even though the map vi ...

The component encounters a transformation in which prop values shift to undefined

My component seems to be encountering some instability. The value assigned to "this.state.list" from this.props is being immediately set to "undefined". I'm struggling to comprehend why this is happening. Can anyone spot the issue in the code? this.s ...

error when sending request using Spring MVC and Ajax

Spring Controller Method : @RequestMapping(value="/checklist/{id}",method=RequestMethod.PUT, consumes=MediaType.APPLICATION_JSON_VALUE , produces=MediaType.APPLICATION_JSON_VALUE) @ResponseBody public Checklist update(@RequestBody Checklist c ...

Tips for triggering functions when a user closes the browser or tab in Angular 9

I've exhausted all my research efforts in trying to find a solution that actually works. The problem I am facing is getting two methods from two different services to run when the browser or tab is closed. I attempted using the fetch API, which worke ...