How to show hierarchical data in tabular format using ng-repeat - angularjs

i am new in angular. so i was reading write up just to accomplish my job. this way i will try but not sure that am i going in right direction? here is my sample code
<ul>
<li ng-repeat="parent in items">{{parent.pitem}}
<ul>
<li ng-repeat="child in parent.citems">{{child.pitem }}</li>
</ul>
</li>
</ul>
var app = angular.module('myapp', []);
app.controller('MyCtrl', function ($scope) {
$scope.items = [{ "pitem": "Coffee", "citems": "" }, { "pitem": "Tea", "citems": [{ "pitem": "Black tea", "citems": "" }, { "pitem": "Green tea", "citems": "" }] }, { "pitem": "Milk", "citems": "" }]
});
i actually i need to show employee hierarchy like manager and their subordinate.
i also read this too on the same kind of topic written by #zsong https://stackoverflow.com/a/18295177/6188148
so please help me to generate tabular output with ng-repeat using ul,li and end user should be able to expand collapse rows too. please have a look at this url http://maxazan.github.io/jquery-treegrid/examples/example-bootstrap-3.html i want similar kind of output but with ng-repeat.
see this url http://www.lidorsystems.com/support/articles/angularjs/treegrid/tree-grid-filter.aspx then can understand what kind of output i am trying to build with ng-repeat.
please guide and suggestion.

This JSFiddle https://jsfiddle.net/benfosterdev/NP7P5/ shows exactly what you are looking for:
Recursion
<div ng-app="app" ng-controller='AppCtrl'>
<script type="text/ng-template" id="categoryTree">
{{ category.title }}
<ul ng-if="category.categories">
<li ng-repeat="category in category.categories" ng-include="'categoryTree'">
</li>
</ul>
</script>
<ul>
<li ng-repeat="category in categories" ng-include="'categoryTree'"></li>
</ul>
</div>
Json object
$scope.categories = [
{
title: 'Computers',
categories: [
{
title: 'Laptops',
categories: [
{
title: 'Ultrabooks'
},
{
title: 'Macbooks'
}
]
},
{
title: 'Desktops'
},
{
title: 'Tablets',
categories: [
{
title: 'Apple'
},
{
title: 'Android'
}
]
}
]
},
{
title: 'Printers'
}
];
});

Related

Is there any way to bind the function name from a JSON data to the (click) of a button in angular

Hi I want to assign method name dynamically and use them.Please help.
I am trying something like following.
<div class="dashboard row">
<div class="card col-lg-3" *ngFor="let card of cards">
<h5 class="card-title">{{card.title}}</h5>
<div class="card-body">
<ul style="list-style-type:none;">
<li *ngFor="let cardFeature of cardFeatures" style="padding-left: 7px;">
{{cardFeature.title}}
<button (click)="[cardFeature.method]">{{cardFeature.method}}</button>
</li>
</ul>
</div>
</div>
CardFeatures is an array where I am defining the JSON data and there I am defining my method name so that I can dynamically read call that. But I am unable to achieve the goal.
Please help to resolve the same.
This is what I have in my ts file
cardFeatures = [
{
"name": "id",
"title": "ID",
"enable": true,
"link": "/register",
"method": "meth1()"
},
{
"name": "profile",
"title": "profile",
"enable": true,
"link": "/link1",
"method": "meth2()"
}
]
cards = [
{
title: "Card1"
},
{
title: "Card2"
}]
Try like this:
Working Demo
cardFeatures = [
{
name: "id",
title: "ID",
enable: true,
link: "/register",
method: () => this.meth1()
},
{
name: "profile",
title: "profile",
enable: true,
link: "/link1",
method: () => this.meth2()
}
];
Template:
<div class="card-body">
<ul style="list-style-type:none;">
<li *ngFor="let cardFeature of cardFeatures" style="padding-left: 7px;">
{{cardFeature.title}}
<button (click)="cardFeature.method()">Test</button>
</li>
</ul>
</div>
EDIT:
As per your comment, you can also try this solution

How to call another key from ng-repeat source

Pardon me if the question sounds weird. Suppose I have the following object:
// For example purposes, pretend that link gets pushed to $scope.links 5 times.
var link = {
name: "name",
description: "description",
members: [{
memname: "member name"
}],
active: true
}
$scope.links.push(link);
...and I used $scope.links as follows
<li ng-repeat="item in links">
<li ng-repeat = "member in item.members">
...
</li>
</li>
...and inside the list with member in item.members, I want to use link.active for ng-show. Is it possible to do so?
Something like:
<li ng-repeat="member in item.members" ng-show="item.active">.
Please advise.
Thank you.
Created Snippet for you .
function myCtrl($scope) {
$scope.links = [{
'name': "name",
'description': "description",
'members': [{
'memname': "member name"
},{
'memname': "member name 2"
}],
'active': true
},{
'name': "name 2",
'description': "description",
'members': [{
'memname': "member name"
},{
'memname': "member name 2"
}],
'active': false
}]
//$scope.links.push(link);
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app ng-controller="myCtrl">
<ul>
<li ng-repeat="item in links" ng-show="item.active == true">
{{item.name}}
<ul >
<li ng-repeat = "member in item.members" >
{{member.memname}}
</li>
</ul>
</li>
</ul>
</div>
Hope this will help you.

Submenu doesn´t show/hide on my ng-click($index)

I'm trying to do a tree menu on my site.
I want the subitems to show/hide when I click the parent.
This solution don't work. Even tho it changes the item.active value to false/true. Any ides my friends?
Here is my HTML:
<div id="sidebar-wrapper">
<div class="cssTreeMenu tree">
<ul class="sidebar-nav">
<li ng-repeat="item in items" >
<a ui-sref="{{item.sref}}" ui-sref-active="active" ng-click="testcolaps($index)">{{item.name}}</a>
<ul ng-show="{{item.active}}" class="navbarColorOnClick">
<li ng-repeat="subItem in item.subItems" ui-sref-active="active">
<a ui-sref="{{subItem.sref}}">{{subItem.name}}</a>
</li>
</ul>
</li>
</ul>
</div>
Here is my controller:
$scope.testcolaps = function (index) {
$scope.items[index].active = !$scope.items[index].active;
};
$scope.items = [
{
name: "Test",
sref: "kpi.test",
active: false,
subItems: [
{
name: "Selectable KPI menu",
sref: "kpi.selectableKpiMenu"
},
{
name: "Test",
sref: "kpi.test"
}
]
},
{
name: "Test2",
sref: "kpi.test",
active: false,
subItems: [
{
name: "Selectable KPI menu 2",
sref: "kpi"
},
{
name: "Test 2",
sref: "internal"
}
]
},
];
As you can se my items have a active: property who I change to true/false. But still nothing happens in my menu. If I hard-code it to true it is showing like it should but still the click-event doesn't work.
The expression inside the ng-show need an expression without {{}} interpolation. Basically you need to remove {{}}.
ng-show="item.active"

AngularJS Scope don't call elements

Hi guys this exercise with scopes don't run,
View:
<body ng-controller="marcasController">
<ul>
<li ng-repeat="todo in marcas">
{{todo.nombre}}
<ul>
<li ng-repeat="tipo in todo.modelo">{{tipo.nombre}}</li>
</ul>
</li>
</ul>
</body>
Controller:
app.controller('marcasController', ['$scope', function($scope) {
$scope.marcas =
[{
"marcas": [
{
"marca": "Chevrolet",
"modelo": [
{
"nombre": "Aveo",
"image": "images/aveo.jpg",
"modelo": "2000-2014",
"tab": "aveo"
},
{
"nombre": "Captiva",
"image": "images/captiva.jpg",
"modelo": "2000-2014",
"tab": "captiva"
}
]
}
]
}];
}])
Example
please how use scopes to call objects
Given that data structure you should be doing it like this:
<ul>
<li ng-repeat="todo in marcas[0].marcas">
{{todo.marca}}
<ul>
<li ng-repeat="tipo in todo.modelo">{{tipo.nombre}}</li>
</ul>
</li>
</ul>
Example
Notice that $scope.marcas is an Array of objects that contains just one element, that element has only one attribute: marcas which is another Array...
Maybe you wanted that data structure to be like this instead:
$scope.marcas =[
{
"marca": "Chevrolet",
"modelo": [
{
"nombre": "Aveo",
"image": "images/aveo.jpg",
"modelo": "2000-2014",
"tab": "aveo"
},
{
"nombre": "Captiva",
"image": "images/captiva.jpg",
"modelo": "2000-2014",
"tab": "captiva"
}
]
}
];
In that case, the correct syntax for your view would be:
<ul>
<li ng-repeat="todo in marcas">
{{todo.marca}}
<ul>
<li ng-repeat="tipo in todo.modelo">{{tipo.nombre}}</li>
</ul>
</li>
</ul>
Example

How do I cancel drag between different lists when using angular-ui's sortable module

I am using angular-ui's sortable-ui module and am trying to raise a cancel so that the dragged items returns to it original location in the source list. Unfortunately I cannot get this working. Here is an example:
http://jsfiddle.net/Ej99f/1/
var myapp = angular.module('myapp', ['ui.sortable']);
myapp.controller('controller', function ($scope) {
$scope.list = ["1", "2", "3", "4", "5", "6"];
$scope.list2 = ["7", "8", "9"];
$scope.sortableOptions = {
update: function(e, ui) {
if (Number(ui.item.text()) === 6) {
ui.item.parent().sortable('cancel');
}
},
receive: function(e, ui) {
ui.sender.sortable('cancel');
ui.item.parent().sortable('cancel');
},
connectWith: ".group",
axis: 'y'
};
});
angular.bootstrap(document, ['myapp']);
Any help would be gratefully appreciated.
well, when it comes to angular, all roads lead to the data "the single source of truth". So update your model back to it's original state, before the move, and you're all set :)
example below has two lists, the first one being restricted for
its sorting (the update method)
and for sending an item (receive method on list 2)
the second list you can sort, and send items to list 1
(using foundation4 for css)
<div ng-app="test">
<div ng-controller="sortableTest">
<div class="small-4 columns panel">
<ul data-drop="true"
ui-sortable="sortable.options.list1" ng-model="sortable.model.list1">
<li ng-repeat="fruit in sortable.model.list1"
data-id="{{ fruit.id }}">{{ fruit.label }}</li>
</ul>
</div>
<div class="small-4 columns panel">
<ul data-drop="true"
ui-sortable="sortable.options.list2" ng-model="sortable.model.list2">
<li ng-repeat="element in sortable.model.list2"
data-id="{{ element.id }}">{{ element.label }}</li>
</ul>
</div>
<div class="clear"></div>
<br />
<span ng-repeat="fruit in sortable.model.list1">{{ fruit.label }} </span><br />
<span ng-repeat="element in sortable.model.list2">{{ element.label }} </span><br />
<span ng-repeat="fruit in sortable.oldData.list1">{{ fruit.label }} </span><br />
<span ng-repeat="element in sortable.oldData.list2">{{ element.label }} </span><br />
</div>
</div>
js:
var test = angular.module('test', ['ui.sortable']);
test.controller('sortableTest', function($scope, $timeout) {
$scope.sortable = {
model: {
list1: [{id: 1, label: 'apple'},{id: 2, label: 'orange'},{id: 3, label: 'pear'},{id: 4, label: 'banana'}],
list2: [{id: 5, label: 'earth'},{id: 6, label: 'wind'},{id: 7, label: 'fire'},{id: 8, label: 'water'}]
},
oldData: {
list1: [],
list2: []
},
options: {
list1: {
update: function(event, ui) {
console.debug('up-list1');
$scope.sortable.oldData.list1 = $scope.sortable.model.list1.slice(0);
$scope.sortable.oldData.list2 = $scope.sortable.model.list2.slice(0);
// DO NOT USE THIS! it messes up the data.
// ui.item.parent().sortable('cancel'); // <--- BUGGY!
// uncomment and check the span repeats..
$timeout(function(){
$scope.sortable.model.list1 = $scope.sortable.oldData.list1;
$scope.sortable.model.list2 = $scope.sortable.oldData.list2;
});
},
connectWith: 'ul'
},
list2: {
update: function(event, ui) {
console.debug('up-list2');
},
connectWith: 'ul',
receive: function(event, ui) {
console.debug('re-list2');
$timeout(function(){
$scope.sortable.model.list1 = $scope.sortable.oldData.list1;
$scope.sortable.model.list2 = $scope.sortable.oldData.list2;
});
}
}
}
};
});
you can of course use a service or something to store the old value. One can use ui.sender to differentiate the senders, if you have more that two..

Resources