Table inside table using ng-repeat in angularjs - javascript

I am new to angularjs and web-development .I am using ng-repeat to represent the data in a complicated table , like this :
A B C D
abc pqr xyz std
So,This is the code :
<div class="table-responsive">
<table class="table table-striped table-bordered report-table table-fixed" contextmenu-container="meta.contextmenu" fixed-header>
<thead class="text-center text-info">
<th class="text-center">A</th>
<th class="text-center">B</th>
<th class="text-center">C</th>
<th class="text-center">D</th>
</thead>
<tr ng-repeat="report in reports.data">
<td class="text-center">{{ report.attributes.annotation }}</td>
<td class="td-report-field" contenteditable="{{enableReportEditing}}" contextmenu-item="report" context-menu="menuOptions">{{ report.attributes.field }}</td>
<td>
<input type="checkbox" ng-if="report.attributes.message && showcheckbox" ng-bind="report.attributes.message" ng-click="getcheckedData(report.attributes.message)">
<span ng-if="report.attributes.message" contentEditable ng-model="report.attributes.message">
{{ report.attributes.message }}
</span>
<span ng-if="!report.attributes.message">{{ report.attributes.message }}</span>
</td>
<td class="text-center">{{ report.attributes.score }}</td>
</tr>
</table>
</div>
And the json is like :
{
"type": "report",
"id": 14,
"attributes": {
"annotation": "abc",
"field": "pqr",
"message": "xyz",
"score": "7"
},
"innerAnnotations": {
{
"annotation": "jkl",
"field": "pqr",
"message": "xyz",
"score": "6"
},
{
"annotation": "Qualification",
"field": "EFG",
"message": "HIJ",
"score": "5"
}
}
},
Now table should look like -(abc will be the parent)
A B C D
abc pqr xyz 7
jkl pqr xyz 6
Qualification EFg Hij 5
So, I have tried some things but no luck. Can any one please help me to solve this ? Any help will be great.

You have mentioned wrong data in ng-repeat
ng-repeat="report in reports.data"
Replace it with
ng-repeat="report in reports.innerAnnotations". Also you need to change the inner html angular expressions too.

Related

Reorder Table columns Angular 8

I have a table built in Angular 8. I am not using Material UI.
I want to reorder the columns in the table using JSON. Is there any way that could be done?
My Angular table code is like below:
<table>
<thead class="thead-light">
<tr>
<th *ngFor="let data of tableHeaders">
{{ data.value }}
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of transactions ">
<td>{{ data.firstName }}</td>
<td>{{ data.regNo }}</td>
<td>{{ data.course }}</td>
</tr>
</tbody>
</table>
My tableheader json:
this.tableHeaders = [
{
"id": 'first_name',
"value":"Name",
},
{
"id": 'reg_no',
"value":"Reg No"
},
{
"id": 'course_name',
"value":"Course"
},
]
While I am able to change the order of the table headers by setting an id and sorting the array - tableHeaders, but how do I do the same for the td?
Any help would be appreciated.
You need to modify header and content's key to make it relate together something like
Full example: Stackblitz
.ts
this.tableHeaders = [
{
"id": 'first_name',
"value":"Name",
"key": "firstName"
},
{
"id": 'reg_no',
"value":"Reg No",
"key":"regNo"
},
{
"id": 'course_name',
"value":"Course",
"key": "course"
},
]
.html
<table>
<thead class="thead-light">
<tr>
<th *ngFor="let data of tableHeaders">
{{ data.value }}
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of transactions">
<td *ngFor="let header of tableHeaders">
{{ data[header.key] }}
</td>
</tr>
</tbody>
</table>

how can i fetch data json from api to Web app page html

I want to fetch all Jason data into a table
How can i do that?
i write code javascript to get json data from my api, but i can't fetch all data like "category" "name" "value" to table in page html !!
api json :
[
{ "allinfo":[
{
"category": "category1",
"info": [{
"name": "Tech1",
"value": "1575"
},
{
"name": "tech2",
"value": "a-25"
}
]
},
{
"category": "category2",
"info": [{
"name": "Announced",
"value": "2022"
},
{
"name": "Status",
"value": "Coming soon"
}
]
},
{
"category": "category3",
"info": [{
"name": "with",
"value": "163.3 cm"
},
{
"name": "Weight",
"value": "500 g"
}
]
}]
}]
code javascript :
$.getJSON('https://myapi', function(data) {
console.log(data);
$.each(data, function(index, value) {
console.log(value);
var category = value.allinfo.category;
var name = value.allinfo.info.name;
var value = value.allinfo.info.value;
$('.output').append('<div class="cont"><h3>' + category + '</h3><table><tbody><tr><td>'+ name +'</td><td>' + value + '</td></tr></tbody></table></div>');});});
html :
<div class="output"></div>
output html:
<div class="cont">
<h3>undefined</h3>
<table>
<tbody>
<tr>
<td>undefined</td>
<td>undefined</td>
</tr>
<tr>
<td>undefined</td>
<td>undefined</td>
</tr>
</tbody>
</table>
</div>
i want to be like this :
<div class="cont">
<h3>category1</h3>
<table>
<tbody>
<tr>
<td>Tech1</td>
<td>1575</td>
</tr>
<tr>
<td>tech2</td>
<td>a-25</td>
</tr>
</tbody>
</table>
</div>
<div class="cont">
<h3>category2</h3>
<table>
<tbody>
<tr>
<td>Announced</td>
<td>2022</td>
</tr>
<tr>
<td>Status</td>
<td>Coming soon</td>
</tr>
</tbody>
</table>
</div>
<div class="cont">
<h3>category3</h3>
<table>
<tbody>
<tr>
<td>with</td>
<td>163.3 cm</td>
</tr>
<tr>
<td>Weight</td>
<td>500 g</td>
</tr>
</tbody>
</table>
</div>
How can i do that?
I appreciate your help
Here is a short way of doing the whole thing in one expression:
const da=[{ "allinfo":[
{"category": "category1",
"info":[{"name":"Tech1","value":"1575"},
{"name":"tech2","value": "a-25"}]},
{"category": "category2",
"info":[{"name": "Announced","value": "2022"},
{"name": "Status","value": "Coming soon"}]},
{"category": "category3",
"info":[{"name": "with","value": "163.3 cm"},
{"name": "Weight","value": "500 g"}]}
]}];
document.querySelector("div.cont").innerHTML=da[0].allinfo.map(cat=>
`<h1>${cat.category}</h1>
<table><tbody>${cat.info.map(r=>
`<tr><td>${r.name}</td><td>${r.value}</td></tr>`).join("")}
</tbody></table>`).join("\n")
td {border:1px solid grey; width:100px}
table{border-collapse:collapse}
<div class="cont"></div>
There are two (nested) .map()s looping over
da[0].categories for all tables using cat for each category and
cat.info for all records r in one category
The output of each map() is .join()-ed and the resulting string is assigned to the first encountered div.cont's .innerHTML.
You can access your Obj properties like this:
To get category:
var cat = value[0].allinfo[1].category
console.log(cat) //category2
To get info:
var name = value[0].allinfo[1].info[0].name
console.log(name) //announced
Pay attention: to your variable names, it appears that you name all variables as "name"!

Angular display table header only once and hide header if no data

I am using Angular 5.
When typeId is equal to 3, I would like to display table header only once.
And also when none of data’s typeId is equal to 3, I want to hide the whole table, do not show table header any more.
Please see my code and data below:
Code:
<table>
<ng-container *ngFor="let attachment of data.Data.Summary.Attachment">
<ng-container *ngIf="attachment.typeId=='3'">
<thead>
<tr>
<th>File</th>
<th>Description</th>
<th>Date</th>
</tr>
</thead>
</ng-container>
</ng-container>
<tbody>
<ng-container *ngFor="let attachment of data.Data.Summary.Attachment">
<tr *ngIf="attachment.typeId=='3'">
<td>{{ attachment.file }}</td>
<td>{{ attachment.description }}</td>
<td>{{ attachment.date }}</td>
</tr>
</ng-container>
</tbody>
</table>
Data:
{
"Data": {
"Summary": {
"Attachment": [
{
"typeId": "3",
"file": "a.pdf",
"description": "File A",
"date": "05/03/2017"
},
{
"typeId": "3",
"file": "b.pdf",
"description": "File B",
"date": "05/03/2017"
},
{
"typeId": "1",
"file": "c.pdf",
"description": "File C",
"date": "05/03/2017"
},
{
"typeId": "3",
"file": "d.pdf",
"description": "File D",
"date": "05/03/2017"
}
]
}
}
}
Result:
File Description Date
a.pdf File A 05/03/2017
b.pdf File B 05/03/2017
d.pdf File D 05/03/2017
Thank you in advance.
This isn't really an "angular" problem, more a javascript problem. In your component, you can create a method isHeaderVisible() which decides if the header should be visible or not and use that. Something like:
isHeaderVisible() {
return this.data.Data.Summary.Attachment.some(attachment => attachment.typeId === '3')
}
Separately, it'd probably be better to do your data filtering in your component, rather than your component's template. So do something like
visibleAttachments() {
return this.data.Data.Summary.Attachment.filter(attachment => attachment.typeId === '3')
}
Put them together and your template might look like:
<table>
<thead *ngIf="isHeaderVisible()">
<tr>
<th>File</th>
<th>Description</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let attachment of visibleAttachments()">
<td>{{ attachment.file }}</td>
<td>{{ attachment.description }}</td>
<td>{{ attachment.date }}</td>
</tr>
</tbody>
</table>
Or you could simply do <thead *ngIf="visibleAttachments().length > 0"> and get rid of isHeaderVisible(). And at this point, you might as well move the *ngIf to the <table> element instead of the <thead> element, because it sounds like you only want to display this table if an attachment with typeId === '3' exists.
So:
<table *ngIf="visibleAttachments().length > 0">
<thead>
<tr>
<th>File</th>
<th>Description</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let attachment of visibleAttachments()">
<td>{{ attachment.file }}</td>
<td>{{ attachment.description }}</td>
<td>{{ attachment.date }}</td>
</tr>
</tbody>
</table>

angularJS nesting ng-repeat

I have data in the following format.
[
{
"id": "1",
"quizId": "2",
"question": "What team is Messi playing ?",
"quiz": [
{
"id": "2",
"categoryId": "67",
"name": "Football Quiz",
"quizsize": "0"
}
],
"answers": [
{
"id": "1",
"questionId": "1",
"name": "Barcelona",
"correct": "1"
},
{
"id": "2",
"questionId": "1",
"name": "M.City",
"correct": "0"
},
{
"id": "3",
"questionId": "1",
"name": "Real Madrid",
"correct": "0"
},
{
"id": "4",
"questionId": "1",
"name": "Liverpool",
"correct": "0"
}
]
}
]
I trying to display it in a table.
Each question(the root) is a row, the for one td I get the quiz.name and then I'm trying to display the answers.name as well.
<table class="table table-striped">
<tr>
<th>Title</th>
<th>Category</th>
<th>Answer 1</th>
<th>Answer 2</th>
<th>Answer 3</th>
<th>Answer 4</th>
</tr>
<tr ng-repeat="question in questions">
<td>{{ question.question}}</td>
<td>{{ question.quiz[0].name }}</td>
<td ng-repeat="answer in question.answers">
<td>{{ answer.name}}</td>
</td>
</tr>
</table>
The second ng-repeat does not display anything.
I also tried answer[0].name.
Your current HTML is invalid as per standards.
td element can not be nested, you should use different element to display content inside td like div or span
Markup
<tr ng-repeat="question in questions">
<td>{{ question.question}}</td>
<td>{{ question.quiz[0].name }}</td>
<td ng-repeat="answer in question.answers">
<div>{{ answer.name}}</div>
</td>
</tr>

nested arrays with ng-repeat and table html

I want to take this json place it into a HTML table.
"columns" : [
{
"id" : 0,
"column_name" : "Column 1",
"cards" : [
{
"id" : 0,
"task" : "Task 1"
},
{
"id" : 1,
"task" : "Task 2"
}
]
},
{
"id" : 1,
"column_name" : "Column 2",
"cards" : [
{
"id" : 0,
"task" : "Task 3"
}
]
}]
I have done quite a bit of searching on SO and cannot find why it is not doing what I expect.
https://jsfiddle.net/6nh100ca/9/
This is what I am expecting.
**Column 1 | Column 2**
Task 1 | Task 3
Task 2 |
https://stackoverflow.com/a/20063394/3279550
http://www.bennadel.com/blog/2456-grouping-nested-ngrepeat-lists-in-angularjs.htm
https://stackoverflow.com/a/26607425/3279550
This is what I have
<table >
<thead >
<tr>
<th ng-repeat="column in entity.columns">{{column.column_name}}</th>
</tr>
</thead>
<tbody ng-repeat="column in entity.columns" >
<tr ng-repeat="card in column.cards">
<td >{{card.task}}</td>
</tr>
</tbody>
</table>
If you want to stick with creating your own <table> manually, you need to pre-process your data object in order to fit the row logic. Try something like this fiddle:
Add this in your controller:
$scope.rowColumns = [];
$scope.columns.forEach(function(column, columnIndex){
column.cards.forEach(function (card, rowIndex){
if (!$scope.rowColumns[rowIndex])
$scope.rowColumns[rowIndex] = [];
$scope.rowColumns[rowIndex][columnIndex] = card;
});
});
console.log($scope.rowColumns);
Then add this in your html:
<tr ng-repeat="row in rowColumns">
<td ng-repeat="cell in row">
{{cell.task}}
</td>
</tr>
column.columnName should be column.column_name as per your example data, there after you could have two ng-repeat over a data where you will be actually have 1st ng-repeat over tbody & then the another will appear on tr. I'd prefer this approach when I have small data set. For larger data set the answer given by #Tiago is fine.
<table >
<thead >
<tr>
<th ng-repeat="column in entity.columns">{{column.columnName}}</th>
</tr>
</thead>
<tbody ng-repeat="column in entity.columns" >
<tr ng-repeat="card in column.cards">
<td >{{card.task}}</td>
</tr>
</tbody>
</table>

Categories

Resources