present nested data in table using angularjs - html

Using angular 1.4.7
I have the following javascript object
var parents = [
{"name" : "John",
childs:[{ "name" : "Child1", age:"4"},{"name" : "Child2",age:"8"}]},
{"name" : "Peter",
childs:[{ "name" : "Child3", age:"5"},{"name" : "Child", age:"12"}]}
]
and I want to have the following output as html table
<table>
<tr>
<td>John</td>
<td>Child1</td>
<td>4</td>
</tr>
<tr>
<td></td>
<td>Child2</td>
<td>8</td>
</tr>
<tr>
<td>Peter</td>
<td>Child3</td>
<td>5</td>
</tr>
<tr>
<td></td>
<td>Child3</td>
<td>12</td>
</tr>
</table>
I have been trying using ng-repet-start to insert a new row (</tr><tr>) within the child loop.
<tr ng-repeat-start="parent in parents">
<td >
{{parent.name}}
</td>
<td ng-repeat-start="child in parent.childs">
{{child.name}}
</td>
<td>
{{child.age}}
<!--new row within child loop and -->
</tr>
<tr>
<td></td>
<td ng-repeat-end></td>
<tr ng-repeat-end></tr>
The error I get in the console is:
Unterminated attribute, found 'ng-repeat-start' but no matching 'ng-repeat-end' found.
If I take out the </tr><tr> I get no error, but also not the desired output.

This code will give you almost the output you've asked (some extra <tbody> tags there, but it's still valid html):
<table>
<tbody ng-repeat="parent in parents">
<tr ng-repeat="child in parent.childs">
<td ng-if = "$index == 0">{{parent.name}}</td>
<td ng-if = "$index != 0"></td>
<td >
{{child.name}}
</td>
<td>{{child.age}}</td>
</tr>
</tbody>
</table>
Here is working Plunk
I should say, that implementation is quite ugly. I would used <td rowspan="number_of children"> to achieve similar visual result. See implementation here, with rowspan and a little bit of bootstrap.
<table class = "table table-condensed">
<tbody ng-repeat="parent in parents">
<tr ng-repeat="child in parent.childs">
<td ng-if="$index == 0" rowspan="{{parent.childs.length}}">{{parent.name}}</td>
<td>
{{child.name}}
</td>
<td>{{child.age}}</td>
</tr>
</tbody>
</table>
EDIT: updated Plunker
Dirty implementation for data with 'grandchildren'
$scope.withGrandChildren = [
{"name" : "John",
childs:[
{ "name" : "Child1",
age:"42",
grandchildrens:[
{"name":"Graddchildren1_1", age:"12"} ,
{"name":"Grandchildren1_2", age:"17"}
]
},
{ "name" : "Child2",
age:"38",
grandchildrens:[
{"name":"Graddchildren2_1", age:"19"}
]
}
]
},
{"name" : "Peter",
childs:[
{ "name" : "Child3", age:"45"},
{"name" : "Child", age:"12"}
]
}
]

Try this instead:
<tbody ng-repeat="parent in parents">
<tr ng-repeat="child in parent.childs">
<td>{{parent.name}}</td>
<td >
{{child.name}}
</td>
<td>{{child.age}}</td>
</tr>
</tbody>
The only difference of this with your desired output is that the parent name is displayed for all child rows

Related

Need help on how to use a bootstrap table component in my Angular project

I just started learning Angular 5 and I found this interesting data table format that I want to use in my Angular project: https://bootsnipp.com/snippets/featured/condensed-table-example, especially to get a different color for each label in a column like in the "status" column in the link above.
In this example, labels are hardcoded in the table while in my case I would like to get them straight from my database and display them on the UI(with color variation).
<div class="container">
<div class="row">
<div class="span5">
<table class="table table-striped table-condensed">
<thead>
<tr>
<th>Username</th>
<th>Date registered</th>
<th>Role</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>Donna R. Folse</td>
<td>2012/05/06</td>
<td>Editor</td>
<td><span class="label label-success">Active</span>
</td>
</tr>
<tr>
<td>Emily F. Burns</td>
<td>2011/12/01</td>
<td>Staff</td>
<td><span class="label label-important">Banned</span></td>
</tr>
<tr>
<td>Andrew A. Stout</td>
<td>2010/08/21</td>
<td>User</td>
<td><span class="label">Inactive</span></td>
</tr>
<tr>
<td>Mary M. Bryan</td>
<td>2009/04/11</td>
<td>Editor</td>
<td><span class="label label-warning">Pending</span></td>
</tr>
<tr>
<td>Mary A. Lewis</td>
<td>2007/02/01</td>
<td>Staff</td>
<td><span class="label label-success">Active</span></td>
</tr>
</tbody>
</table>
I was thinking about using ngSwitch but I am not sure. Any idea on how to do it? Thanks!
I think you could use the [ngStyle] directive
considering that you have a users array xD
you could set something like
<ul *ngFor ="let user of users">
<li [ngStyle]="{'background':getColor(user.status)}">{{user.name}}{{user.status}}</li>
</ul>
and do an function like this in your TS
getColor(status){
switch (status){
case "Inactive":
return 'gray';
case "Banned":
return 'red';
case "Active":
return 'green';
}
and lets say
users: any[] = [
{
"name" : "The First dude",
"status" : "Banned"
},
{
"name" : "The second one",
"status" : "Active"
}
];
in that case every time that an user is called, the function getColor will be triggered and will return a color to the background of the :P
Sorry about my english xD i have a lot to learn

Unable to display NO DATA message when data does not exist in the table

I am displaying table data using NgTableParams in angularjs. I was trying to show NO DATA EXISTS in the table when the data is not available or length is zero, but my code doesn't seems to work.
Demo : http://plnkr.co/edit/nEbjQE1NQW7VF8dlZvyy?p=preview
sample code:
<table ng-table="tableParams" class="table" show-filter="true">
<tbody ng-repeat="user in $data">
<tr ng-show="$data.length > 0">
<td title="'Name'" filter="{ name: 'text'}" sortable="'name'">
{{user.name}}</td>
<td title="'Age'" filter="{ age: 'number'}" sortable="'age'">
{{user.age}}</td>
</tr>
<tr ng-show="$data.length === 0">
<td title="'Name'" filter="{ name: 'text'}" sortable="'name'">
NO DATA FOUND</td>
<td title="'Age'" filter="{ age: 'number'}" sortable="'age'">
</td>
</tr>
</tbody>
js code:
app.controller('MainCtrl', function($scope, NgTableParams) {
$scope.data1 = [];
console.log(" $scope.data1 length " + $scope.data1.length);
$scope.tableParams = new NgTableParams({}, { dataset: $scope.data1});
});
Tried as below too , but it is not displaying the table header and filter for the columns..
Demo : http://plnkr.co/edit/XAOO5tPALVOkQW9hhJCs?p=preview:
<tbody ng-show="!$data.length">
<tr>
<td>
NO DATA FOUND
</td>
</tr>
</tbody>
<tbody ng-repeat="user in $data">
<tr ng-show="$data.length > 0">
....
</tbody>
There are two issues here
The first one is that your ng-repeat directive is in your tbody this will cause your table body to be rendered for every single element in your array.
The second one is that your "NO DATA FOUND" message is inside of your ng-repeat block, no element will be rendered if $data is empty.
The solution would be to move the ng-repeat from your tbody to the actual element that you want to repeat for every item in your array, in this case, the tr that contains the data to be displayed.
<table ng-table="tableParams" class="table" show-filter="true">
<tbody>
<tr ng-repeat="user in $data" ng-show="$data.length > 0">
<td title="'Name'" filter="{ name: 'text'}" sortable="'name'">
{{user.name}}</td>
<td title="'Age'" filter="{ age: 'number'}" sortable="'age'">
{{user.age}}</td>
</tr>
<tr ng-show="$data.length === 0">
<td title="'Name'" filter="{ name: 'text'}" sortable="'name'">
NO DATA FOUND</td>
<td title="'Age'" filter="{ age: 'number'}" sortable="'age'"></td>
</tr>
</tbody>
</table>
Hope it helps!

Nested ng-repeat will not loop if first field is undefined?

I am attempting to do a nested loop to access the tutor information and the logs the students made for the tutor in my HTML
HTML:
<table ng-if="vm.log.length !== 0 && vm.checked === 1" class="table table-striped">
<thead>
<tr>
<th>Tutor First Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="log in vm.logs ">
<td>{{logs.tutorFirst}}</td>
<td>
<table>
<tr ng-repeat="Student in StudentLogs track by $index">
<td> {{Student.log}}</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
JSON:
[
"Tutorfirst" :"tutor"
],
[
"Tutorfirst" :"tutor"
"Student" :{
"log" : "INFO"
}
],
The JSON might not be correct but my question is,
Will the ng-repeat initiate if the first object does not have the field i'm trying to loop?

Angularjs, two data in a single row in table

I have a problem to implement table with thin width.
myData = { name:"Foo", age:11, sex:"M", weight:77, height:77, hobby:'gaming'}
I wanna table like belows.
<table>
<tr>
<td>name</td><td>Foo</td><td>age</td><td>11</td>
</tr>
<tr>
<td>sex</td><td>M</td><td>weight</td><td>77</td>
</tr>
<tr>
<td>height</td><td>77</td><td>hobby</td><td>gaming</td>
</tr>
</table>
Is it possible to show data like this using ngRepeat and its built-in variable?
The question John posted would solve your problem but I think it would be less of a hack to use ng-repeat-start and ng-repeat-end e.g.:
<table>
<tr ng-repeat-start="item in myData">
<td>name</td><td>{{item.name}}</td><td>age</td><td>{{item.age}}</td>
</tr>
<tr>
<td>sex</td><td>{{item.sex}}</td><td>weight</td><td>{{item.weight}}</td>
</tr>
<tr ng-repeat-end>
<td>height</td><td>{{item.height}}</td><td>hobby</td><td>{{item.hobby}}</td>
</tr>
</table>
If you have yr myData like this :
myData = [{ name:"Foo", age:11, sex:"M", weight:77, height:77, hobby:'gaming'},{ name:"Foo", age:11, sex:"M", weight:77, height:77, hobby:'gaming'},{ name:"Foo", age:11, sex:"M", weight:77, height:77, hobby:'gaming'}]
Then Your table will be like this :
<table>
<tr ng-repeat="row in myData">
<td>{{row.name}}</td>
<td>{{row.age}}</td>
<td>{{row.sex}}</td>
<td>{{row.weight}}</td>
<td>{{row.height}}</td>
<td>{{row.hobby}}</td>
</tr>
</table>

AngularJS nested ng-repat in ng-repeat (key, value) pair data structure in HTML table element with sort filter

I want to print table rows from the fallowing data structure.
$scope.myData = {}
myData['Item1']['Period1']= {"Value":1}
myData['Item1']['Period2']= {"Value":2}
myData['Item1']['Period3']= {"Value":3}
myData['Item1']['Period4']= {"Value":4}
myData['Item2']['Period1']= {"Value":11}
myData['Item2']['Period2']= {"Value":12}
myData['Item3']['Period3']= {"Value":13}
myData['Item4']['Period4']= {"Value":14}
I want to print it somehow like this and sort by Period name DESC:
<tbody >
<tr ng-repeat="(key, value) in myData">
<td>
{{ key }}
</td>
<td ng-repeat="PeriodItem in value | <!-- here the filtering -->">
{{ PeriodItem.Value }}
</td>
</tr>
</tbody>
The key is printed out, but the PeriodItem.Value is not. What is the proper way to do that, because i tried a couple of things and none of them seem to work.
Example of desired output:
<tbody>
<tr>
<td>Item1</td>
<td>4</td>
<td>3</td>
<td>2</td>
<td>1</td>
</tr>
<tr>
<td>Item2</td>
<td>14</td>
<td>13</td>
<td>12</td>
<td>11</td>
</tr>
</tbody>
try this fiddle
<tbody >
<tr ng-repeat="(key, value) in myData">
<td>
{{ key }}
</td>
<td ng-repeat="(key, value) in value">
{{ value.Value }}
</td>
</tr>
</tbody>
when using ng-repeat, "(key, value) in blah" syntax is used to iterate hashes.
"value in blah" is used to iterate arrays
You've defined your data as
myData['Item1']['Period1']= {"Value":1}
myData['Item1']['Period2']= {"Value":2}
...
which is a bit confusing. If you restructure it, it should be clear whether the second dimension is an array or hash.
$scope.myData = {
Item1: {
Period1: {Value: 1},
Period2: {Value: 2},
Period3: {Value: 3},
Period4: {Value: 4},
},
Item2: {
Period1: {Value: 11},
Period2: {Value: 22},
...