I want to generate dynamic table with dynamic table header and row/columns according to json object comes from webapi.
Here are examples of json object which comes every time different.
[
{"Country":"Australia","Toner Quantity":8},
{"Country":"China","Toner Quantity":6},
{"Country":"India","Toner Quantity":11},
{"Country":"South Korea","Toner Quantity":1}
]
and some time it comes like
[
{"CustomerName":"FORD","Australia":0,"China":2,"India":0,"South Korea":0},
{"CustomerName":"ICICI PRUDENTIAL","Australia":0,"China":0,"India":5,"South Korea":0},
{"CustomerName":"Kimberly Clark","Australia":0,"China":0,"India":0,"South Korea":1},
{"CustomerName":"McDonalds","Australia":1,"China":0,"India":0,"South Korea":0},
{"CustomerName":"Novartis","Australia":1,"China":0,"India":0,"South Korea":0},
{"CustomerName":"Origin Energy","Australia":3,"China":0,"India":0,"South Korea":0}
]
So I have tried but not able to achieve dynamic table with headers and row/columns
my html code like
<table class="table striped">
<thead>
<tr role="row">
<th ng-repeat="th in dataconfigureListData.previewData">{{th}}</th>
</tr>
</thead>
<tbody>
<tr role="row" data-ng-repeat="previewData in dataconfigureListData.previewData">
<td> {{previewData.Country}}</td>
<td> {{previewData['Total Toner Qty']}}</td>
</tr>
</tbody>
</table>
You can do this by using an ng-repeat inside another. And also, use the first line to render the headers.
Note on ngRepeat: For some reason, angularjs#1.4.0 previous versions sorted the keys alphabetically when using ng-repeat by key in object. A simple way to fix that is upgrading to angularjs#^1.4.0 which is where they fixed it.
Announce of this change by angular docs:
You need to be aware that the JavaScript specification does not define the order of keys returned for an object. (To mitigate this in Angular 1.3 the ngRepeat directive used to sort the keys alphabetically.)
Version 1.4 removed the alphabetic sorting. We now rely on the order returned by the browser when running for key in myObj. It seems that browsers generally follow the strategy of providing keys in the order in which they were defined, although there are exceptions when keys are deleted and reinstated. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-browser_issues
Ref.: Iterating over object properties
The following snippet implements this solution.
angular.module('myApp', [])
.controller('myController', function($scope) {
$scope.myArray = [
{ "CustomerName": "FORD", "Australia": 0, "China": 2, "India": 0, "South Korea": 0 },
{ "CustomerName": "ICICI PRUDENTIAL", "Australia": 0, "China": 0, "India": 5, "South Korea": 0 },
{ "CustomerName": "Kimberly Clark", "Australia": 0, "China": 0, "India": 0, "South Korea": 1 },
{ "CustomerName": "McDonalds", "Australia": 1, "China": 0, "India": 0, "South Korea": 0 },
{ "CustomerName": "Novartis", "Australia": 1, "China": 0, "India": 0, "South Korea": 0 },
{ "CustomerName": "Origin Energy", "Australia": 3, "China": 0, "India": 0, "South Korea": 0 }
];
});
angular.element(document).ready(function() {
angular.bootstrap(document, ['myApp']);
});
table {
border-collapse: collapse;
}
td,
th {
padding: 2px 4px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<table ng-controller="myController" border="1">
<tr>
<th ng-repeat="(key, val) in myArray[0]">{{ key }}</th>
</tr>
<tr ng-repeat="row in myArray">
<td ng-repeat="column in row">
{{ column }}
</td>
</tr>
</table>
The example bellow implements sorting columns dynamically by clicking on the column's header and also with reverse by clicking again on the selected column
angular.module('myApp', [])
.controller('myController', function($scope) {
$scope.sortByColumn = 'CustomerName';
$scope.sortByReverse = false;
$scope.sortBy = function(column) {
if (column === $scope.sortByColumn) {
$scope.sortByReverse = !$scope.sortByReverse;
} else {
$scope.sortByReverse = false;
}
$scope.sortByColumn = column;
};
$scope.getSortColumn = function () {
// it has to be like this, otherwize, the `orderBy sortByColumn`
// breaks for special names like "South Korea"
return '"' + $scope.sortByColumn + '"';
};
$scope.myArray = [
{ "CustomerName": "FORD", "Australia": 0, "China": 2, "India": 0, "South Korea": 0 },
{ "CustomerName": "ICICI PRUDENTIAL", "Australia": 0, "China": 0, "India": 5, "South Korea": 0 },
{ "CustomerName": "Kimberly Clark", "Australia": 0, "China": 0, "India": 0, "South Korea": 1 },
{ "CustomerName": "McDonalds", "Australia": 1, "China": 0, "India": 0, "South Korea": 0 },
{ "CustomerName": "Novartis", "Australia": 1, "China": 0, "India": 0, "South Korea": 0 },
{ "CustomerName": "Origin Energy", "Australia": 3, "China": 0, "India": 0, "South Korea": 0 }
];
});
angular.element(document).ready(function() {
angular.bootstrap(document, ['myApp']);
});
table {
border-collapse: collapse;
}
td,
th {
padding: 2px 4px;
}
[ng-click] {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
<table ng-controller="myController" border="1">
<tr>
<th ng-repeat="(key, val) in myArray[0]" ng-click="sortBy(key)">
{{ key }}
<span ng-if="sortByColumn === key">{{ sortByReverse ? '▲' : '▼' }}</span>
</th>
</tr>
<tr ng-repeat="row in myArray | orderBy : getSortColumn() : sortByReverse">
<td ng-repeat="column in row">
{{ column }}
</td>
</tr>
</table>
The logic is to get the header by iterating on the first object props using Object.keys.
To get only the values from to the cells itself you can do ng-repeat with (key, value) in some_obj.
Here is a full example:
angular.module('app', []).
controller('ctrl', function($scope) {
$scope.data1 = [
{"Country":"Australia","Toner Quantity":8},
{"Country":"China","Toner Quantity":6},
{"Country":"India","Toner Quantity":11},
{"Country":"South Korea","Toner Quantity":1}
];
$scope.data2 = [
{"CustomerName":"FORD","Australia":0,"China":2,"India":0,"South Korea":0},
{"CustomerName":"ICICI PRUDENTIAL","Australia":0,"China":0,"India":5,"South Korea":0},
{"CustomerName":"Kimberly Clark","Australia":0,"China":0,"India":0,"South Korea":1},
{"CustomerName":"McDonalds","Australia":1,"China":0,"India":0,"South Korea":0},
{"CustomerName":"Novartis","Australia":1,"China":0,"India":0,"South Korea":0},
{"CustomerName":"Origin Energy","Australia":3,"China":0,"India":0,"South Korea":0}
];
$scope.getHeaders = function(arr) {
return Object.keys(arr[0]);
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<table>
<tr>
<td ng-repeat="header in getHeaders(data1)">{{header}}</td>
</tr>
<tr ng-repeat="row in data1">
<td ng-repeat="(key, value) in row">{{value}}</td>
</tr>
</table>
<hr />
<table>
<tr>
<td ng-repeat="header in getHeaders(data2)">{{header}}</td>
</tr>
<tr ng-repeat="row in data2">
<td ng-repeat="(key, value) in row">{{value}}</td>
</tr>
</table>
</div>
i'm using angular 1.6
Here marked columns are dynamic as well as its values.
My table structures are below.
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>Doctor</th>
<th>Target</th>
<th ng-repeat="brand in doctorTargets.brands">{|| brand.name ||}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in doctorTargets.doctorTargets">
<td>{|| item.doctorName ||}</td>
<td>{|| item.target ||}</td>
<td ng-repeat="brand in item.brands">{||brand.target||</td>
</tr>
</tbody>
</table>
Related
I am working with some data collected from a Json file. With a react fetch function I have created an object called "category_evolution". I am trying to use a map function to create a table with that object.
category_evolution =
[
{
"name": "01/02/2023",
"data": [
{
"id": 30,
"category": "Criptomoedas",
"category_total_brl": "12000.00",
"category_total_usd": "2400.00",
"date": "01/02/2023"
},
{
"id": 28,
"category": "REITs",
"category_total_brl": "16000.00",
"category_total_usd": "3200.00",
"date": "01/02/2023"
},
{
"id": 26,
"category": "Stocks",
"category_total_brl": "20100.00",
"category_total_usd": "4020.00",
"date": "01/02/2023"
}
]
},
{
"name": "01/01/2023",
"data": [
{
"id": 29,
"category": "Criptomoedas",
"category_total_brl": "10000.00",
"category_total_usd": "2000.00",
"date": "01/01/2023"
},
{
"id": 27,
"category": "REITs",
"category_total_brl": "15000.00",
"category_total_usd": "3000.00",
"date": "01/01/2023"
},
{
"id": 25,
"category": "Stocks",
"category_total_brl": "20000.00",
"category_total_usd": "4000.00",
"date": "01/01/2023"
}
]
}
]
Here is my table code:
<table className="table">
<thead>
<tr>
<th scope="col">Categoria</th>
{category_evolution.map(({ name }) => (
<th scope="col" key={name}>{name}</th>
))}
</tr>
</thead>
<tbody>
{category_evolution.map(({ data }) =>
data.map(({ id, category, category_total_brl }) => (
<tr key={id}>
<td>{category}</td>
<td>{category_total_brl}</td>
</tr>
))
)}
</tbody>
</table>
The output of this code is a table like that
Categoria 01/02/2023 01/01/2023
Criptomoedas 12000.00
REITs 16000.00
Stocks 20100.00
Criptomoedas 10000.00
REITs 15000.00
Stocks 20000.00
But I would like to achieve an output like this:
Categoria 01/02/2023 01/01/2023
Criptomoedas 12000.00 10000.00
REITs 16000.00 15000.00
Stocks 20100.00 20000.00
I appreciate any help you can provide.
One way to do it is to combine all the data into a single array and then to map that array into an object where keys are the categories and the values are combined data for each "date":
const combinedData = category_evolution.reduce((acc, cur) => {
return [...acc, ...cur.data];
}, []);
const categoryMap = combinedData.reduce((acc, cur) => {
if(!acc[cur.category]) {
acc[cur.category] = [cur];
return acc;
}
acc[cur.category].push(cur);
return acc;
}, {});
And then the JSX:
<table className="table">
<thead>
<tr>
<th scope="col">Categoria</th>
{category_evolution.map(({ name }) => (
<th scope="col" key={name}>{name}</th>
))}
</tr>
</thead>
<tbody>
{Object.keys(categoryMap).map(category => {
return (
<tr key={category}>
<th>{category}</th>
<td>{categoryMap[category][0].category_total_brl}</td>
<td>{categoryMap[category][1].category_total_brl}</td>
</tr>
)
})}
</tbody>
</table>
Combined data provided from #o4ohel
const combinedData = category_evolution.reduce((acc, cur) => {
return [...acc, ...cur.data];
}, []);
const categoryMap = combinedData.reduce((acc, cur) => {
if(!acc[cur.category]) {
acc[cur.category] = [cur];
return acc;
}
acc[cur.category].push(cur);
return acc;
}, {});
Here's an updated version of the code provided by #o4ohel that can be improved for readability and maintainability:
<table className="table">
<thead>
<tr>
<th scope="col">Categoria</th>
{category_evolution.map(({ name }) => (
<th scope="col" key={name}>{name}</th>
))}
</tr>
</thead>
<tbody>
{Object.entries(categoryMap).map(([category, values]) => (
<tr key={category}>
<th>{category}</th>
{values.map(({ id, category_total_brl }) => (
<td key={id}>{category_total_brl}</td>
))}
</tr>
))}
</tbody>
</table>
A nested map is used to iterate over the values for each category, which allows for greater flexibility in case there are more or less values for each category in the future.
I have JSON structure like below:
const villages =
{
"lossesOccured":
[
{
"type": "destroyed",
"affectedOn": "humans",
"quantity": 120,
"reliefFund": 100000,
"location": {
"district": "thanjavur",
"villageName": "madukkur",
"pincode": "614903"
}
},
{
"type": "physicalDamage",
"affectedOn": "humans",
"quantity": 250,
"reliefFund": 50000,
"location": {
"district": "thanjavur",
"villageName": "madukkur",
"pincode": "614903"
}
},
]
}
I need help in displaying the JSON data in the form of table like below Using React. Also, need the table row to be added automatically whenever a new element is added in JSON.
<table>
<thead>
<tr>
<th>AffectedOn</th>
<th>Type</th>
<th>Quantity</th>
</tr>
</thead>
<tbody>
{
villages.lossesOccured.map(loss => (
<tr>
<td>{loss.affectedOn}</td>
<td>{loss.type}</td>
<td>{loss.quantity}</td>
</tr>
)
}
</tbody>
</table>
I have a JSON array like this:
[
{
"students": {
"Student1": {
"number": "15",
"books": {
"Mystery": [
"Book1",
"Book2"
]
}
},
"Student2": {
"number": "12",
"books": {
"Romance": [
"Book1"
],
"Adventure": [
"Book1",
"Book2"
]
}
},
"Student3": {
"number": "116",
"books": {
}
}
},
"class": "7th Grade",
"school": "High School 1"
}
]
I want to display this data as a table on an Angular1 page in the following manner:
How can I make it so that the columns resize with each other, and how can I have nested ng-repeats as needed?
I tried to have nested tables inside the student, student-number, and books columns, and a table within the table in the books column, but the alignment was always off, and I couldn't get a default value of "No Books" to show up if the "books" field was empty.
Here's a Plunkr of what I've tried so far.
One of possible solutions is to combine several tables(based on $scope.base, $scope.students, $scope.books arrays, that calculated in controller) into one virtual, desired table via float:left(to ensure they located in one row). Docking of rows is provided by setting of their style:height, which depends on number of their children. Direct solution will be very complicated due to complicated html markup of table with rowspan attributes. Also I added second item(items.push(items[0])), to demonstrate, that solution works at case of several items.
angular.module('app', [])
.controller('MyController', ['$scope', function($scope) {
var items = [
{
"students": {
"Student1": {
"number": "15",
"books": {
"Mystery": [
"Book1",
"Book2"
]
}
},
"Student2": {
"number": "12",
"books": {
"Romance": [
"Book1"
],
"Adventure": [
"Book1",
"Book2"
]
}
},
"Student3": {
"number": "116",
"books": {
}
},
"class": "7th Grade",
"school": "High School 1"
}
}
];
items.push(items[0]);
$scope.base = [];
$scope.students = [];
$scope.books = [];
for(var item of items){
var temp = $scope.books.length;
for(var student in item.students){
if(['class', 'school'].indexOf(student) == -1){
var studentV = item.students[student];
$scope.students.push({name:student, number: studentV.number, w: Object.keys(studentV.books).length || 1});
for(var book in studentV.books)
$scope.books.push((book + ':' + JSON.stringify(studentV.books[book])).replace(/"/g, ''));
if(Object.keys(studentV.books).length == 0)
$scope.books.push('No books');
}
}
$scope.base.push({cl: item.students.class, school: item.students.school, w: $scope.books.length - temp});
}
}]);
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
table.left, table.left th, table.left td {
border-right: 0px
}
tr {
text-align:center
}
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<div ng-app='app' ng-controller="MyController">
<table style='float:left;border-right:0' class='left'>
<thead>
<tr>
<th>School</th>
<th>Class</th>
</tr>
</thead>
<tbody>
<tr ng-repeat='item in base' style='height:{{item.w*30}}px'>
<td>{{item.school}}</td>
<td>{{item.cl}}</td>
</tr>
</tbody>
</table>
<table style='float:left' class='left'>
<thead>
<tr>
<th>Student</th>
<th>Student-number</th>
</tr>
</thead>
<tbody>
<tr ng-repeat='item in students' style='height:{{item.w*30}}px'>
<td>{{item.name}}</td>
<td>{{item.number}}</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>Books</th>
</tr>
</thead>
<tbody>
<tr ng-repeat='item in books track by $index' style='height:30px'>
<td>{{item}}</td>
</tr>
</tbody>
</table>
</div>
I chose to create hidden nested tables to show more information upon click.
I have a REST service, which returns this object:
[
{
"id": 100,
"value": "2452"
},
{
"id": 100,
"value": "2458"
},
{
"id": 1,
"value": "2457"
},
{
"id": 1,
"value": "2459"
},
{
"id": 4,
"value": "2460"
},
{
"id": 5,
"value": "3458"
}
]
Now, using this GET service, I want the following table to be built in angular and show it in UI.
100 1 4 5
-------------------
2452 2457 2460 3458
2458 2459
i.e. the unique ids should create the header and the list of values associates to each header value will be appended to respective column.
I have tried something with ng-repeat like this:
<table border="1">
<tr>
<th ng-repeat="column in cols">{{column.id}}</th>
</tr>
<tr>
<td ng-repeat="column in cols">
<md-list>
<md-list-item class="md-2-line" ng-repeat="val in column.values">
<md-checkbox ng-model="item.done"></md-checkbox>
<div class="md-list-item-text">
??
</div>
</md-list-item>
</md-list>
</td>
</tr>
But still wondering how to do the same? Please help.
Try use groupBy filter.
var app = angular.module('anApp', ['angular.filter']);
app.controller('aCtrl', function($scope) {
$scope.data = [
{
"id": 100,
"value": "2452"
},
{
"id": 100,
"value": "2458"
},
{
"id": 1,
"value": "2457"
},
{
"id": 1,
"value": "2459"
},
{
"id": 4,
"value": "2460"
},
{
"id": 5,
"value": "3458"
}
];
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-filter/0.4.7/angular-filter.js"></script>
<div ng-app="anApp" ng-controller="aCtrl">
<table border="1">
<tr>
<th ng-repeat="col in data | groupBy: 'id'">{{col[0].id}}</th>
</tr>
<tbody>
<tr>
<td ng-repeat="col in data | groupBy: 'id'">
<table>
<tr ng-repeat="c in col">
<td> {{c.value}}</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
</div>
I am using MEAN stack in my application with AngularJS as my front-end. How to total sum inside of array values in angularjs , actually we have used ng-repeat inside of one more ng-repeat to fetch the value in table and I got the fetched value like 250 in Sprice then I'm expecting to totalsum the sprice value like as a ans= 250.
My Plunker.
We have used two ng-repeat to get the sprice values in table because sprice is in inside of the [array].
We need to calculate total sum of sprice of value in table.
We have filter functionality to calculate the totalsum of ng-module value if it is in without array.
Actually we dont' know how to use resultValue= in ng-repeat.
For example: sprice value is 250 in table means the totalsum value need to be in 250, if sprice value is 250 and 300 means expecting answer like 550.
Without array totalsum functionality: My Plunker
With array totalsum functionality: My Plunker
My Controller:
.filter('sumOfValue', function () {
return function (data, key) {
debugger;
if (angular.isUndefined(data) && angular.isUndefined(key))
return 0;
var sum = 0;
angular.forEach(data,function(v,k){
sum = sum + parseFloat(v[key]);
});
return sum.toFixed(2);
}
})
My Data:-
$scope.orders = [
{
"_id": "5836b64083d9ce0f0078eae8",
"user": {
"_id": "579bdf6123f37f0e00a40deb",
"displayName": "Table 1"
},
"__v": 8,
"total": "1824",
"ordercar": [],
"orderfood": [
{
"qty": "1",
"confirm": "placed",
"sprice": 250,
"price": 250,
"customise": "With Onion,Without Onion",
"name": "Baasha Pizza"
}
],
"phone": null,
"order_source": "",
"comment": "",
"payment_mode": "",
"nop": null,
"rating": null,
"bill": false,
"complete": false,
"laundry": false,
"clean": false,
"roomservice": false,
"napkin": false,
"waiter": false,
"water": false,
"name": "fgg",
"created": "2016-11-24T09:43:28.413Z",
"isCurrentUserOwner": true
}]
My Html:-
<table ng-table="tableParams" class="table table-bordered ">
<thead>
<tr>
<th rowspan="2">s.no</th>
<th rowspan="2"> sprice </th>
</tr>
</thead>
<tr ng-repeat="order in orders">
<td>{{$index + 1}}</td>
<td ng-repeat="ram in order.orderfood">{{ram.sprice }}</td>
</tr>
<tr>
<td>sum</td>
<td>{{resultValue | sumOfValue:'sprice'}}</td>
</tr>
</table>
*We expecting for total sum in array values.
Used ng-repeat:
<tr ng-repeat="order in orders">
<td>{{$index + 1}}</td>
<td ng-repeat="ram in order.orderfood">{{ram.sprice }}</td>
ng-repeat is not looping properly .. I fixed it .. Check below snippet and also i added one more array to it.......... let me know..
var app = angular.module('plunker', []);
app.filter('sumOfValue', function () {
return function (data, key) {
debugger;
if (angular.isUndefined(data) && angular.isUndefined(key))
return 0;
var sum = 0;
angular.forEach(data,function(v,k){
sum = sum + parseFloat(v[key]);
});
return sum.toFixed(2);
}
}).controller('MainCtrl', function($scope) {
$scope.orders = [
{
"_id": "5836b64083d9ce0f0078eae8",
"user": {
"_id": "579bdf6123f37f0e00a40deb",
"displayName": "Table 1"
},
"__v": 8,
"total": "1824",
"ordercar": [],
"orderfood": [
{
"qty": "1",
"confirm": "placed",
"sprice": 250,
"price": 250,
"customise": "With Onion,Without Onion",
"name": "Baasha Pizza"
},
{
"qty": "2",
"confirm": "placed",
"sprice": 250,
"price": 250,
"customise": "With Onion,Without Onion",
"name": "Baasha Pizza"
}
],
"phone": null,
"order_source": "",
"comment": "",
"payment_mode": "",
"nop": null,
"rating": null,
"bill": false,
"complete": false,
"laundry": false,
"clean": false,
"roomservice": false,
"napkin": false,
"waiter": false,
"water": false,
"name": "fgg",
"created": "2016-11-24T09:43:28.413Z",
"isCurrentUserOwner": true
}]
});
body {
font-size: 14px;
}
table
{
border-collapse:collapse;
}
table, td, th
{
border:1px solid black;
}
td{
padding: 2px;
}
.servicetaxinclusivetrue:before{
color: green!important;
content: "\f00c";
}
.servicetaxinclusivefalse:before{
color: red!important;
content: "\f00d";
}
.servicetaxexclusivetrue:before{
color: green!important;
content: "\f00c";
}
.servicetaxexclusivefalse:before{
color: red!important;
content: "\f00d";
}
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css">
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.12/angular.js" data-semver="1.4.9"></script>
</head>
<body ng-controller="MainCtrl">
<table ng-table="tableParams" class="table table-bordered ">
<thead>
<tr>
<th rowspan="2">s.no</th>
<th rowspan="2"> sprice </th>
</tr>
</thead>
<tbody ng-repeat="order in orders">
<tr ng-repeat="ram in resultValue=(order.orderfood)">
<td>{{$index + 1}}</td>
<td >{{ram.sprice }}</td>
</tr>
<tr>
<td>sum</td>
<td>{{resultValue | sumOfValue:'sprice'}}</td>
</tr>
</tbody>
</table>
</body>
</html>
Here you can call function using "ng-init", so that angularjs will call function before execution of "ng-repeat".
In that function you can perform iteration and calculate total and hold it in scope variable to display it.