Recursive ng-repeat x times - javascript

I need to repeat over a deeply nested javascript object in my angular template. The problem is that I have no control over how the data is handed to me, and no way of knowing how deeply nested the data will be.
The data looks like this
{
category_name: 'cat1'
children: [
{
category_name: 'cat1a',
children: [...]
}
]
}
And the template
<div ng-repeat="cat in categories">
<div ng-repeat="subcat in cat.children">
{{subcat.name}}
<!--
would like to programatically place an ng-repeat here too
if subcat.children.length > 0
-->
</div>
{{cat.name}}
</div>
This checks two levels deep, but how can I recursively repeat until there are no children left? I'm thinking I need to create a custom directive that compiles a new ng-repeat as required, I'm just not sure how to go about it.

You can use ng-include with a directive script type ng-template/text and call it recursively to write n children. (PLUNKER)
<body ng-controller="MainCtrl as vm">
<script type="text/ng-template" id="nested.html">
{{item.category_name}}
<ul>
<li ng-repeat="item in item.children" ng-include="'nested.html'"></li>
</ul>
</script>
<ul>
<li ng-repeat="item in vm.data" ng-include="'nested.html'"></li>
</ul>
</body>
Check angular docs for more info: https://docs.angularjs.org/api/ng/directive/script

Try the following:
module.js
var app = angular.module('app', []);
app.component("category", {
controller: function() {
this.data = {
category_name: 'cat1',
children: [{
category_name: 'cat1-A',
children: [{
category_name: 'cat1-A-a',
children: [{
category_name: 'cat1-A-a-1',
children: []
},
{
category_name: 'cat1-A-a-2',
children: []
}
]
}]
}]
};
},
template: '<child current-cat="$ctrl.data"></child>'
});
app.component("child", {
template: '<div>{{$ctrl.currentCat.category_name}}' +
'<div style="padding-left:20px;" ng-repeat="cat in $ctrl.currentCat.children">' +
'<child current-cat="cat"></child>' +
'</div>' +
'</div>',
bindings: {
currentCat: '<'
}
});
index.html
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.js"></script>
<script src="module.js"></script>
</head>
<body ng-app="app">
<div>
<category></category>
</div>
</body>
</html>

Related

Implementing an accordion in AngularJS and better understanding $scope

I am editing an already existing Angular webpage. In the app.js file, there are multiple controllers for each page. Here's their template:
JS:
app.controller("myCtrl", function($scope) {
$scope.useSettings({
Header: "header",
Title: "title",
mainImg: "main.png",
fields: [{
fieldText: "text",
},{
fieldImg: "pic.jpg",
},{
fieldAccordion:
//
},{
]
});
});
My goal is to have fieldAccordion work as an accordion for the data that I input there, just how all my fields work.
This is my Unordered List data type in the html file:
<div class="basic-page__field__undordered" ng-
if="field.fieldUnorderedList">
<ul class="field-list field-list--unordered">
<li ng-repeat="listItem in field.fieldUnorderedList">{{ listItem }}
</li>
</ul>
</div>
I can simply use it in the .JS file like this:
fieldUnorderedList: [
"item1",
"item2",
]
So I would like to find a similar way to use data for an accordion type.
Here is how I wrote it in the .html file:
<div class="basic-page__field__accordion" ng-if="field.fieldAccordion">
<ul class="field-list field-list--accordion">
<li ng-repeat="item in items" ng-click="accordion.current = item.name">
{{item.name}}
<ul ng-show="accordion.current == item.name">
<li ng-repeat="sub in item.sub">{{sub.name}}</li>
</ul>
</li>
</ul>
</div>
Now the issue that I'm having is getting it to work as simple as using
"fieldAccordion:" in my controller.
I have done some research and what I don't understand is this:
All my controllers have the same template with $scope.useSettings, followed by all the data such as fieldText, fieldImg, etc.
How would I add another $scope that deals with the accordion data type which I can use in the exact place that I want it to be?
Something like this:
$scope.accordion = {
current: null
};
$scope.items = [{
name: 'List 1',
sub: [{
name: 'Sub 1.1'
},{
name: 'Sub 1.2'
}]
},{
name: 'List 2',
sub: [{
name: 'Sub 2.1'
}]
},{
name: 'List 3',
sub: [{
name: 'Sub 3.1'
},{
name: 'Sub 3.2'
},{
name: 'Sub 3.3'
}]
}];
}]);
This is one of my biggest obstacles in getting to understand AngularJS. Since I am working on an already existing webpage, I don't know how to add multiple $scopes for one controllers and where to use them. Any help is appreciated.

How to create a tree structure in Knockout using a Knockout template?

I am working with Knockout support and now creating tree structured UI component. Here i will create the elements dynamically and there i want to bind the data to newly created elements.
Please check with the below code
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script type="text/html" id="tree">
<li menuid="data bind with attr binding">
<span> </span>
<span><a href="#" name="endnode"></span>
<ul data-bind="template: { name: 'tree', foreach: childNodes }">
</ul>
</li>
below is my script
var viewModel = {
Mytree: ko.observable({
childNodes: [
{
id: 1,name:"node1",
childNodes: [ {id: 2, name:"node2", childNodes: [{id: 3,name:"node3", childNodes: [] }] } ]
},
{
id: 4,name:"node4",
childNodes: [ {id: 5,name:"node5", childNodes: [] } ]
}
]
})
};
ko.applyBindings(new viewModel.Mytree());
Now i want to append the bindable node names to to tree like below:
<span><a href="#" name="endnode" data-bind:"text:childNodes.name"/></span>
<ul data-bind="template: { name: 'tree', foreach: childNodes }">
Can you please any one suggest me to achieve this
If you pass it the view model (you can use the $root syntax for this) you can just use "name" in the binding. The context will change as it goes down the tree ... there's a couple of other bits wrong - for one it's data-bind= (equals, not colon)
Try this template ...
<script type="text/html" id="tree">
<li menuid="data bind with attr binding">
<span> </span>
<ul data-bind="template: { name: 'tree', foreach: childNodes }" />
</li>
</script>
and use this to kick things off (note $root)
<ul data-bind="template: { name: 'tree', data: $root }" />
this will give you ...

Nested ng-repeat angularjs

I have an value like that my problem is i don't know how much nested that dummy array object so how to use ng-repeat that print all dummy array object
demo: [{
id: 1,
dummy: [
{
id: 1,
dummy: [
{
id: 1,
dummy: [
{
id: 1
}
]
}
]
}
]
}]
try like this. as this answers: How to put ng-repeat inside ng-repeat for n number of times
and How can I make recursive templates in AngularJS when using nested objects?
var app = angular.module("app", []);
app.controller('mainCtrl', function($scope){
$scope.demo = [{
id: 1,
dummy: [
{
id: 1,
dummy: [
{
id: 1,
dummy: [
{
id: 1,
dummy: [
{
id: 1,
dummy:[]
}
]
}
]
}
]
}
]
}]
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.2/css/font-awesome.min.css" rel="stylesheet"/>
<div ng-app="app" ng-controller="mainCtrl">
<script type="text/ng-template" id="dummy.html">
<ul>
<li ng-repeat="d in demo" >
<div >{{d.id}}</div>
<div ng-show="d.dummy.length" ng-include=" 'dummy.html' " onload="demo = d.dummy"></div>
</li>
</ul>
</script>
<div ng-include=" 'dummy.html'" ></div>
</div>

Error in listing tree structure using ng-repeat in angularjs

I am trying to list a nested dictionary on html using ng-repeat
Here is the full code
But it seems like I can't access the value of dictionary key by
tree.value
as it either doesn't show up or will only print
'tree.value'
Can someone help me out?
<div ng-app>
<script type="text/ng-template" id="myTemplate">
<li>X</li>
<p>1 tree.value</p>
<ul ng-repeat="tree in tree.children" ng-include="'myTemplate'">
<p>2 tree.value</p>
</ul>
</script>
<div>
<ul ng-include="'myTemplate'"
ng-init="tree =
{
children:
[
{children: [], value: c12},
{
children:
[
{children: [], value: c112},
{children: [], value: c111}
],
value: c11
}
],
value: c1
}
"></ul>
</div>
</div>
You json is wrongly defined, you should always wrap string value inside single quotes ' like value: c111 & value: 'c112' values should be like value: 'c111' & value: 'c112'
Markup
<ul ng-include="'myTemplate'"
ng-init="tree =
{
children:
[
{children: [], value: 'c12'},
{
children:
[
{children: [], value: 'c112'},
{children: [], value: 'c111'}
],
value: c11
}
],
value: c1
}
"></ul>
More better would be define tree variable inside $scope rather than on html.
Working JSFiddle
it seems c1 is object not string.so c1 has properties.for example c1 has text property.
you should write in template {{tree.value.text}}

how to execute function on ng-repeater running

Hi I have problem with ng-repeater in angular I want to execute function to do calculation on run my problem now the function is not execute when I pass the Id https://jsfiddle.net/gkqL3zdp/1/
can someone help me ?
<div ng-app="app" ng-controller="ctrl">
<div ng-repeat="category in model.categories"> <span> Category: {{ category.name }} </span>
<div ng-click="getID(category.Id)">
</div>
</div>
debugger;
angular.module("app", [])
.controller('ctrl', ['$scope',
function ($scope) {
$scope.model = {
categories: [{
"Id": 1,
name: '1'
}, {
"Id": 2,
name: '2'
},{
"Id": 3,
name: '3'
},{
"Id": 4,
name: '4'
}]
}
$scope.getID = function(id){
id=+2
console.log(parentId)
return result;
}
}])
You can use ng-init for that.
On the same div use something like:
<div ng-repeat="repeatExpression">
<div ng-init="getId()"></div>
</diV>
your clickable divs were 0 height and your parentId and result variables were undefined. I fixed in https://jsfiddle.net/gkqL3zdp/1/
$scope.getID = function(id){
console.log(id)
return id;
}

Categories

Resources