I need to have the possibility to print out a possible infinite deep array-structure into a list. Here's the code from a modified AngularJS-example where I have added some more deep children in the array. How can I print child of child and even its children as well? Is there a way I can get it to repeat forever as long as there is more children?
HTML
<div ng-app>
<div ng-controller="TodoCtrl">
<ul>
<li ng-repeat="todo in todos">
<span>{{todo.text}}</span>
<ul>
<li ng-repeat="child in todo.children">
<span>{{child.text}}</span>
<!-- What about the next one -->
</li>
</ul>
</li>
</ul>
</div>
</div>
JS
function TodoCtrl($scope) {
$scope.todos = [{
text: 'root 1',
children: [{
text: 'child of root 1',
children: [{
text: 'child of child',
children: []
}]
}]
}, {
text: 'root 2',
children: []
}];
}
Fiddle: https://jsfiddle.net/U3pVM/25866/
You can use the view recursively this way:
<script type="text/ng-template" id="todo.html">
<div>
<div>{{ todo.text }}</div>
<ul>
<li ng-repeat="todo in todo.children" ng-include="'todo.html'"></li>
</ul>
</div>
</script>
<div ng-controller="MyController">
<ul>
<li ng-repeat="todo in todos" ng-include="'todo.html'"></li>
</ul>
</div>
Here the DEMO based on your sample data.
Related
I'm trying to render the list with vue.js. The data has come from api call.
List rendering is ok, until I try to add data-feature_id="#{{searched_feature.id}}" in li tag.
When I add it, I got an error:
[Vue warn]: Error compiling template:......
<div class="search_feature_select">
<ul>
<li v-for="searched_feature in searched_features" data-feature_id="#{{searched_feature.id}}" #click="add_to_features_list">
#{{searched_feature.name}}
</li>
</ul>
</div>
How can I put searched_feature.id in data-feature_id attribute?
You need to add : before the attribute
<div class="search_feature_select">
<ul>
<li v-for="searched_feature in searched_features" :data-feature_id="searched_feature.id" #click="add_to_features_list">
{{searched_feature.name}}
</li>
</ul>
</div>
if you wish to add the '#' in front of the data-feature_id attribute:
<div class="search_feature_select">
<ul>
<li v-for="searched_feature in searched_features" :data-feature_id="'#' + searched_feature.id" #click="add_to_features_list">
{{searched_feature.name}}
</li>
</ul>
</div>
https://v2.vuejs.org/v2/guide/list.html coughcough*
var app = new Vue({
el: "#app",
data: {
searched_features: [
{
id: 1,
name: "One"
},
{
id: 2,
name: "Two"
},
{
id: 3,
name: "Three"
}
]
},
methods: {
add_to_features_list(){}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="search_feature_select">
<ul>
<li v-for="searched_feature in searched_features" :data-feature_id="searched_feature.id" #click="add_to_features_list">
#{{ searched_feature.name }}
</li>
</ul>
</div>
</div>
Add 'v-bind:' prefix of shorthand ':' before attribute to bind dynamic data.
<div class="search_feature_select">
<ul>
<li v-for="searched_feature in searched_features"
:data-feature_id="searched_feature.id"
#click="add_to_features_list">
{{searched_feature.name}}
</li>
</ul>
</div>
See more https://v2.vuejs.org/v2/api/#v-bind
I need to add a class on selected <li> like I have shown in demo but dont want it to be removed if I click on another <li>.
Please help
<div ng-app="myApp">
<ul ng-controller="myCtrl">
<li ng-repeat="item in model.items" class="commonClass" ng-class="{'on': model.selected==item}" ng-click="model.selected=item">{{ item.name }}</li>
</ul>
</div>
JS
var app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope) {
$scope.model = {
selected: null,
items : [
{name: "Apple"},
{name: "Banana"},
{name: "California"}
]
};
})
demo
Just add like this
<div ng-app="myApp">
<ul ng-controller="myCtrl">
<li ng-repeat="item in model.items" class="commonClass" ng-class="{'on': selected==$index}" ng-click="selected=$index">{{ item.name }}</li>
</ul>
</div>
This currently lists out all occurrences of the array. I only want to show the array associated for the current item in the parent array.
EG: Instead of listing First Location, Second Location, Third Location. I want it to only list First Location for the First Location, Second Location for the Second Location, etc. What am I missing?
http://plnkr.co/edit/ilgOZzIy2axSi5Iy85C7
var App = angular.module('App', []);
App.controller('locationAccordionCtrl', function ($scope) {
$scope.locations = [
{
"siteName":"First Location",
"locationsList":['First Location 1', 'First Location 2', 'First Location 3']
},
{
"siteName":"Second Location",
"locationsList":['Second Location 1', 'Second Location 2', 'Second Location 3']
},
{
"siteName":"Third Location",
"locationsList":['Third Location 1', 'Third Location 2', 'Third Location 3']
}
];
});
HTML:
<div ng-controller="locationAccordionCtrl">
<div ng-repeat="location in locations">
{{location.siteName}}
<div ng-repeat="location in locations">
<ul>
<li ng-repeat="listOfLocations in location.locationsList track by $index">
{{listOfLocations}}
</li>
</ul>
</div>
</div><!-- /row -->
</div>
You should change:
<div ng-repeat="location in locations">
<ul>
<li ng-repeat="listOfLocations in location.locationsList track by $index">
{{listOfLocations}}
</li>
</ul>
</div>
To this:
<ul>
<li ng-repeat="listOfLocations in location.locationsList track by $index">
{{listOfLocations}}
</li>
</ul>
Hi I want to recreate the following using angularJS.
<div>
<fieldset class="regulated">
<legend>This list was created with html</legend>
<ul>
<li>
<h4>Category1</h4>
<ul>
<li>
<h5>Element1</h5>
<p>Description of Category 1 Element 1</p>
</li>
<li>
<h5>Element2</h5>
<p>Description of Category 1 Element 2</p>
</li>
<li>
<h5>Element1</h5>
<p>Description of Category 1 Element 3</p>
</li>
</ul>
</li>
<li>
<h4>Element2</h4>
<p>Description of element 2</p>
</li>
<li>
<h4>Category2</h4>
<ul>
<li>
<h5>Element1</h5>
<p>Description of Category 2 Element 1</p>
</li>
<li>
<h5>Element2</h5>
<p>Description of Category 2 Element 2</p>
</li>
</ul>
</li>
</ul>
</fieldset>
</div>
Here is how I tried and what I have achieved till now.
This is the html on which my controller is called.
<div>
<fieldset class="regulated" ng-controller="UlController2">
<legend>{{information.header}}</legend>
<ul>
<li ng-repeat="item in items">
<h4>{{item.name}}</h4>
<div ng-bind-html="element(item.followUp)"></div>
</li>
</ul>
</fieldset>
</div>
And this is the controller I am using.
app.controller('UlController2', function($scope,$sce) {
$scope.information = {
header : "This list was created with angular!"
};
$scope.items = [
{'name' : 'Category1', 'followUp' : '<ul></ul>'},
{'name' : 'Element2', 'followUp' : '<p>Description of element 2</p>'},
{'name' : 'Category2', 'followUp' : '<ul></ul>'}
];
$scope.elEments = [
{'name':'Element1','description':'Description of Category 1 Wlement 1'},
{'name':'Element2','description':'Description of Category 1 Wlement 2'},
{'name':'Element3','description':'Description of Category 1 Wlement 3'},
];
$scope.element = function(input){
return $sce.trustAsHtml(input);
}
});
I want to make this without any JQuery or native JavaScript, only AngularJS native methods.
It's not possible with the data you have there because you have no information about the category. It's also difficult for us because your variables names in the controller do not match the ones in the view. Other than that, given you have the information about the category you can do it with two nested ng-repeat.
angular.module('testApp', [])
.controller('testCtrl', ['$scope',
function($scope) {
$scope.categories = [
{
name: 'Category 1',
items: [
{
name: 'Element1',
description: 'Description of Category 1 Element 1'
},
{
name: 'Element2',
description: 'Description of Category 1 Element 2'
},
{
name: 'Element3',
description: 'Description of Category 1 Element 3'
}
]
},
{
name: 'Category 2',
items: [
{
name: 'Element1',
description: 'Description of Category 2 Element 1'
},
{
name: 'Element2',
description: 'Description of Category 2 Element 2'
},
{
name: 'Element3',
description: 'Description of Category 2 Element 3'
}
]
}
]
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="testApp" ng-controller="testCtrl">
<fieldset class="regulated">
<legend>This list was created with angular</legend>
<ul>
<li ng-repeat="category in categories">
<h4>{{category.name}}</h4>
<ul>
<li ng-repeat="item in category.items">
<h5>{{item.name}}</h5>
<p>{{item.description}}</p>
</li>
</ul>
</li>
</ul>
</fieldset>
</div>
I found 2 solutions, both written in angular 1.3.8.
The first is based on Marcel's answer and the other is mine.
This is based on Marcel:
app.controller('UlController2', function($scope, $sce) {
$scope.information = {
header: "This 2nd list was created with angular!"
};
$scope.items = [{
'name': 'Category1',
'innerList': [{
'name': 'Element1',
'description': 'Description of Category 1 Element 1'
}, {
'name': 'Element2',
'description': 'Description of Category 1 Element 2'
}, {
'name': 'Element3',
'description': 'Description of Category 1 Element 3'
}, ]
}, {
'name': 'Element2',
'followUp': 'Description of element 2'
}, {
'name': 'Category2',
'innerList': [{
'name': 'Element1',
'description': 'Description of Category 2 Element 1'
}, {
'name': 'Element2',
'description': 'Description of Category 2 Element 2'
}]
}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js"></script>
<div>
<fieldset class="regulated long">
<legend>This 2nd list was created with html</legend>
<ul>
<li>
<h4>Category1</h4>
<ul>
<li>
<h5>Element1</h5>
<p>Description of Category 1 Element 1</p>
</li>
<li>
<h5>Element2</h5>
<p>Description of Category 1 Element 2</p>
</li>
<li>
<h5>Element1</h5>
<p>Description of Category 1 Element 3</p>
</li>
</ul>
</li>
<li>
<h4>Element2</h4>
<p>Description of element 2</p>
</li>
<li>
<h4>Category2</h4>
<ul>
<li>
<h5>Element1</h5>
<p>Description of Category 2 Element 1</p>
</li>
<li>
<h5>Element2</h5>
<p>Description of Category 2 Element 2</p>
</li>
</ul>
</li>
</ul>
</fieldset>
</div>
<div>
<fieldset class="regulated long" ng-controller="UlController2">
<legend>{{information.header}}</legend>
<ul>
<li ng-repeat="item in items">
<h4>{{item.name}}</h4>
<p>{{item.followUp}}</p>
<ul>
<li ng-repeat="Li in item.innerList">
<h5>{{Li.name}}</h5>
<p>{{Li.description}}</p>
</li>
</ul>
</li>
</ul>
</fieldset>
</div>
And this is mine, simulating the reading of a JSON response.
app.controller('UlController3', function($scope, $sce) {
$scope.information = {
header: "This 3rd list was created with angular!"
};
var items = [{
'name': 'Category1',
'innerList': [{
'name': 'Element1',
'description': 'Description of Category 1 Element 1'
}, {
'name': 'Element2',
'description': 'Description of Category 1 Element 2'
}]
}, {
'name': 'Element2',
'followUp': 'Description of element 2'
}];
$scope.innerUl = function() {
var toAdd = '';
var inner = '';
angular.forEach(items, function(value, key) {
angular.forEach(value, function(firstLiVal, key) {
if (key == 'name') {
toAdd += '<li><h4>' + firstLiVal + '</h4>';
} else if (key == 'followUp') {
toAdd += '<p>' + firstLiVal + '</p></li>';
} else if (key == 'innerList') {
angular.forEach(firstLiVal, function(SecondUlVal, key) {
angular.forEach(SecondUlVal, function(SecondLiVal, key) {
if (key == 'name') {
inner += '<li><h5>' + SecondLiVal + '</h5>';
} else {
inner += '<p>' + SecondLiVal + '</p></li>';
}
});
});
toAdd += '<ul>' + inner + '</ul></li>';
}
});
});
return $sce.trustAsHtml(toAdd);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js"></script>
<div>
<fieldset class="regulated long">
<legend>This 3rd list was created with html</legend>
<ul>
<li>
<h4>Category1</h4>
<ul>
<li>
<h5>Element1</h5>
<p>Description of Category 1 Element 1</p>
</li>
<li>
<h5>Element2</h5>
<p>Description of Category 1 Element 2</p>
</li>
</ul>
</li>
<li>
<h4>Element2</h4>
<p>Description of element 2</p>
</li>
</ul>
</fieldset>
</div>
<div>
<fieldset class="regulated long" ng-controller="UlController3">
<legend>{{information.header}}</legend>
<ul ng-bind-html='innerUl()'></ul>
</fieldset>
</div>
I have following (json) object:
[
{
name: "Foo",
children: [{
name: "bar",
children:[{
...
}]
}]
}
]
There can be any number of children/objects in any level. Now I want to get following HTML Code:
<ul>
<li>Foo</li>
<li>
<ul>
<li>Bar</li>
</ul>
</li>
<ul>
But of course there could be 10 or more levels with 20 or more children per level.
Is there any way to do that? Thank you very much!
this should work, just replace json array with your data
<script type="text/ng-template" id="nodes_renderer.html">
{{node.name}}
<ul ng-model="node.children" ng-class="{hidden: collapsed}">
<li ng-repeat="node in node.children" ng-include="'nodes_renderer.html'">
</li>
</ul>
</script>
<div data-drag-enabled="false">
<ul>
<li ng-repeat="node in #*JSON ARRAY*#" ng-include="'nodes_renderer.html'">
</li>
</ul>
</div>