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?
Related
I have an array booksArr of objects of class book.
book.ts class
export class Book{
bookId:number;
bookName:string;
cost:number;
quantity:number;
constructor(bookId, bookType, cost, quantity){
this.cost=cost;
this.bookId=bookId;
this.bookName=bookName;
this.quantity=quantity;
}}
booksArr in books-list.component.ts
booksArr: book[] = [
new book(100, "The Alchemist", 20, 1),
new book(101, "Rich Dad Poor Dad", 50, 2),
new book(102, "Charolett's Web", 10, 1),
new book(103, "Harry Potter", 70, 4),
new book(104, "Gone Girl", 150, 3),
];
I want to create a table in html to display the details of these books.
books-list.component.html
<table border="1" *ngIf="bName">
<thead>
<tr>
<th>book ID</th>
<th>book Name</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let b of booksArr">
<td *ngIf="b.//WHAT SHOULD I PUT HERE"</td>
</tr>
</tbody>
</table>
You are already iterating through the booksArr.just need to use interpolation to display the data. Try like this
<table border="1" *ngIf="bName">
<thead>
<tr>
<th>book ID</th>
<th>book Name</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let b of booksArr">
<td>{{b.bookId}}</td>
<td>{{b.bookName}}</td>
</tr>
</tbody>
</table>
You are already iterating the array of books with *ngFor="let b of booksArr".
You want to now interpolate the values from each book in the array. When you are inside the array, you have access to the loop variable you declare in *ngFor. In this case the loop variable is b. You can now bind to the properties on b using curly brace interpolation. {{b.bookId}}.
<table border="1" *ngIf="bName">
<thead>
<tr>
<th>book ID</th>
<th>book Name</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let b of booksArr">
<td>{{b.bookId}}</td>
<td>{{b.bookName}}</td>
</tr>
</tbody>
</table>
Try:
<td> {{ b.bookId }} </td>
<td> {{ b.bookName }} </td>
No *ngIf is required in this case. Just try the following
<tbody>
<tr *ngFor="let b of booksArr">
<td>{{b.bookId}}</td>
<td>{{b.bookName}}</td>
</tr>
</tbody>
And in your .ts file you should either change
constructor(bookId, bookName, cost, quantity)
Or
this.bookName=bookType;
inside your constructor
I want to create a table that its data is a Map< String, List < Object> >.
So the table has one header that and the rows should have the exact data.
Map.key
Object.item1
Object.item2
Object.item3
So since it is a List of Object i want one row for every Object of the List and the Map.key to be repeated.
So i need to iterate through keys like
<table>
<thead>
<tr>
<th>Code</th>
<th>Status</th>
<th>Flag</th>
<th>Message</th>
</tr>
</thead>
<tbody>
<tr th:each= "result : ${myMap}">
<td th:text="${result.key}"></td>
<td><table>
<tr th:each="obj: ${result.value}">
<td th:text="${not #lists.isEmpty(obj.errorList)}?'Error':'Warning'"></td>
<td th:text="${obj.flag}==true?'YES':'NO'"></td>
<td th:text="${not #lists.isEmpty(obj.errorList)}?${obj.warningList}:${obj.errorList}"></td>
</tr>
</table></td>
</tr>
</tbody>
</table>
but this solution places a table in a table. I want to use one header and iterate the lists and place the variables in the main table .
I think you're looking for a structure like this:
<table>
<thead>
<tr>
<th>Code</th>
<th>Status</th>
<th>Flag</th>
<th>Message</th>
</tr>
</thead>
<tbody>
<th:block th:each= "result : ${myMap}">
<tr th:each="obj: ${result.value}">
<td th:text="${result.key}" />
<td th:text="${not #lists.isEmpty(obj.errorList)}?'Error':'Warning'" />
<td th:text="${obj.flag}==true?'YES':'NO'" />
<td th:text="${not #lists.isEmpty(obj.errorList)}?${obj.warningList}:${obj.errorList}" />
</tr>
</th:block>
</tbody>
</table>
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
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
I have a WCF service and and we had to generate a records of clients who have consumed free credit.
I have generated that records but now clients with same login ID's are repeating in the records.
I dnt want to display the login ID again but want to display all the numbers they have called.
Here is the code of my view
#model IEnumerable<MyYello.Admin.Models.CallHistory>
#{ViewBag.Title = "UsersWhoHaveConsumedFreeCredit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Users Who Have Consumed Free Credit</h2>
<table class="table table-striped table-bordered tablesorter" style="display: block">
<thead>
<tr>
<th>Login</th>
<th>FirstName</th>
<th>LastName</th>
<th>Email</th>
<th>Country</th>
<th>Phone</th>
<th>TarrifDesc</th>
<th>CalledNum</th>
<th>CallStart</th>
<th>CallEnd</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>#item.Login</td>
<td>#item.FirstName</td>
<td>#item.LastName</td>
<td>#item.Email</td>
<td>#item.Country</td>
<td>#item.Phone</td>
<td>#item.TariffDescription</td>
</tr>
}
#if (!Model.Any())
{
<tr>
<td colspan="14">No Record Found</td>
</tr>
}
</tbody>
</table>
Just need an idea how
You should group by user login first then. Here's an example:
#foreach (var group in Model.GroupBy(history => history.Login))
{
var item = group.First();
<tr>
<td>#item.Login</td>
<td>#item.FirstName</td>
<td>#item.LastName</td>
<td>#item.Email</td>
<td>#item.Country</td>
<td>#string.Join(" - ", group.Select(history => history.Phone))</td>
<td>#item.TariffDescription</td>
</tr>
}