I have a json data with arrays of parameters like Sales, Tax etc. On click of a particular parameter from one page, the landing page should show the table for that particular parameter.
{
"Sales": [
{
"Date": "2015-08-01 23:35:15.652",
"Val": 78
},
{
"Date": "2015-08-01 22:35:15.652",
"Val": 82
},
{
"Date": "2015-08-01 21:35:15.652",
"Val": 80
},
{
"Date": "2015-08-01 21:15:15.652",
"Val": 100
},
{
"Date": "2015-07-27 12:57:15.652",
"Val": 94
}
],
"Tax": [
{
"Date": "2015-08-01 23:35:15.652",
"Min": 78,
"Max":150
},
{
"Date": "2015-08-01 22:35:15.652",
"Min": 50,
"Max":120
},
{
"Date": "2015-08-01 21:35:15.652",
"Min": 65,
"Max":150
},
{
"Date": "2015-08-01 21:25:15.652",
"Min": 70,
"Max":190
},
{
"createdOn": "2015-08-01 21:15:15.652",
"Min": 90,
"Max":200
}
]
}
My controller
angular.module('starter.controllers', [])
.controller('TableCtrl','$scope', '$http', function($scope, $http) {
$http.get('js/data.json').success(function(response){
if(response.data.Sales!=null){
$scope.data =response.data.Sales;
}
if(response.data.Tax!=null){
$scope.data =response.data.Tax;
}
});
});
How do I show table dynamically from the data? Since Sales table will contain 2 columns and Tax table will contain 3 columns.
Table for Sales
<table ng-controller="TableCtrl">
<thead>
<th>
<td>Date</td>
<td>Value</td>
</th>
</thead>
<tbody>
<tr ng-repeat="item in data">
<td>{{item.Date}}</td>
<td>{{item.Val}}</td>
</tr>
</tbody>
</table>
Table for Tax
<table ng-controller="TableCtrl">
<thead>
<th>
<td>Date</td>
<td>Min</td>
<td>Max</td>
</th>
</thead>
<tbody>
<tr ng-repeat="item in data">
<td>{{item.Date}}</td>
<td>{{item.Min}}</td>
<td>{{item.Max}}</td>
</tr>
</tbody>
</table>
How to display different tables based on condition using same Controller, TableCtrl?
In your controller, separate data into $scope.sales and $scope.tax:
if(response.data.Sales != null){
$scope.sales = response.data.Sales;
$scope.tax = null;
}
if(response.data.Tax != null){
$scope.tax = response.data.Tax;
$scope.sales = null;
}
Then, in html use ng-if directive:
<div ng-controller="TableCtrl">
<table ng-if = "sales">
<thead>
<th>
<td>Date</td>
<td>Value</td>
</th>
</thead>
<tbody>
<tr ng-repeat="item in sales">
<td>{{item.Date}}</td>
<td>{{item.Val}}</td>
</tr>
</tbody>
</table>
<table ng-if = "tax">
<thead>
<th>
<td>Date</td>
<td>Min</td>
<td>Max</td>
</th>
</thead>
<tbody>
<tr ng-repeat="item in tax">
<td>{{item.Date}}</td>
<td>{{item.Min}}</td>
<td>{{item.Max}}</td>
</tr>
</tbody>
</table>
</div>
If you have a set of fixed types such as Sales, Tax etc., the hard coded version like #Majid provided is fine. However, you could make a more dynamic version where the table adjusts to the json arrays provided.
Consider the following data:
var data={
"Sales": [
{
"Date": "2015-08-01 23:35:15.652",
"Val": 78
},
{
"Date": "2015-08-01 22:35:15.652",
"Val": 82
},
{
"Date": "2015-08-01 21:35:15.652",
"Val": 80
},
{
"Date": "2015-08-01 21:15:15.652",
"Val": 100
},
{
"Date": "2015-07-27 12:57:15.652",
"Val": 94
}
],
"Tax": [
{
"Date": "2015-08-01 23:35:15.652",
"Min": 78,
"Max":150
},
{
"Date": "2015-08-01 22:35:15.652",
"Min": 50,
"Max":120
},
{
"Date": "2015-08-01 21:35:15.652",
"Min": 65,
"Max":150
},
{
"Date": "2015-08-01 21:25:15.652",
"Min": 70,
"Max":190
},
],
"Inventory": [
{
"Type": "Car",
"Amount": 100,
},
{
"Type": "Bike",
"Amount": 32,
},
{
"Type": "Shoes",
"Amount": 677,
},
]
};
Controller:
function mainCtrl() {
this.data=data;
}
angular
.module('app', [])
.controller('mainCtrl', mainCtrl);
The below html code will now use the first object in each array to print out the property names, and then print each object from the array into to the table accordingly.
<body ng-controller="mainCtrl as main">
<div ng-repeat="(name, table) in main.data">
<h3>{{name}}</h3>
<table>
<thead>
<tr>
<!-- Iterate and print field names -->
<th ng-repeat="(key, value) in table[0]">{{key}}</th>
</tr>
</thead>
<tbody>
<!-- Print rows -->
<tr ng-repeat="row in table">
<td ng-repeat="value in row">{{value}}</td>
</tr>
</tbody>
</table>
</div>
</body>
Live example here: http://jsbin.com/pafanuwoka/edit?html,js,output
Having this solution you need to make sure that all objects in each array are alike as we are printing the field names from the first object in each array. But you are also able to add more json arrays into data field.
If this is a common occurrence in your application, you should probably consider adding this as a directive. Example here: http://jsbin.com/gayirinifo/edit?html,js,output
Related
Data Object:
{
"headers": {
"location": "Location",
"postcode": "Postcode",
"contributors": "Contributors",
"contributions": "Contributions",
"percentage": "Percentage"
},
"rows": [
{
"postcode": "3018",
"contributors": 2,
"contributions": 2,
"location": "Seaholme",
"percentage": 67
},
{
"postcode": "3013",
"contributors": 1,
"contributions": 1,
"location": "Yarraville West",
"percentage": 33
}
]
}
Template:
<thead>
<tr>
<th v-for="(v, k) in data.result.headers" :key="k">
{{ v }}
</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, i) in data.result.rows" :key="i">
<td :key="j" v-for="(col, j) in row">
{{ col }}
</td>
</tr>
</tbody>
Output:
So the table header and body are two separate objects. While the header seems to follow the order but the row objects don't. How can I make sure they always align correctly?
You can create a computed property of the rows. This would be the same list but with the keys ordered in the order of the header keys. Here is a possible solution:
new Vue({
el: "#app",
data: () => ({
"headers": { "location": "Location", "postcode": "Postcode", "contributors": "Contributors", "contributions": "Contributions", "percentage": "Percentage" },
"rows": [
{ "postcode": "3018", "contributors": 2, "contributions": 2, "location": "Seaholme", "percentage": 67 },
{ "postcode": "3013", "contributors": 1, "contributions": 1, "location": "Yarraville West", "percentage": 33 }
]
}),
computed: {
orderedRows() {
const headers = Object.keys(this.headers);
return this.rows.map(row =>
headers.reduce((orderedRow, key) =>
({ ...orderedRow, [key]: row[key] })
, {})
);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<table>
<thead>
<tr>
<th v-for="(v, k) in headers" :key="k">{{ v }}</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, i) in orderedRows" :key="i">
<td v-for="(col, j) in row" :key="j">{{ col }}</td>
</tr>
</tbody>
</table>
</div>
Another possible way inspired from #CertainPerformance comment:
new Vue({
el: "#app",
data: () => ({
"headers": { "location": "Location", "postcode": "Postcode", "contributors": "Contributors", "contributions": "Contributions", "percentage": "Percentage" },
"rows": [
{ "postcode": "3018", "contributors": 2, "contributions": 2, "location": "Seaholme", "percentage": 67 },
{ "postcode": "3013", "contributors": 1, "contributions": 1, "location": "Yarraville West", "percentage": 33 }
]
}),
computed: {
headerKeys() {
return Object.keys(this.headers);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<table>
<thead>
<tr>
<th v-for="(v, k) in headers" :key="k">{{ v }}</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, i) in rows" :key="i">
<td v-for="(header, j) in headerKeys" :key="j">{{ row[header] }}</td>
</tr>
</tbody>
</table>
</div>
I have a nested json array of objects as below. I wanted to parse so that I can read using ng-repeat and display in the html table. In the table, names will become headers and values become cells in each row. can you please help me as how to do this in angularjs ?
[
{
"records":
[
{
"cells": [
{"id": "102", "value": "John"},
{"id": "101", "value": "222"},
{"id": "103", "value": "600987"}
]
},
{
"cells": [
{"id": "103", "value": "69987"},
{"id": "101", "value": "999"},
{"id": "102", "value": "Susan"}
]
}
],
"headers": [
{
"id": "101",
"name": "emp_id"
},
{
"id": "102",
"name": "emp_name"
},
{
"id": "103",
"name": "emp_salary"
}
]
}
]
Here is your table should be like this:
<table>
<tr>
<th ng-repeat="h in list[0].headers">{{h.name}}</th>
</tr>
<tr ng-repeat="record in list[0].records">
<th ng-repeat="cell in record.cells">{{cell.value}}</th>
</tr>
</table>
See a working plunkr https://plnkr.co/edit/MyUaovStvxj58RIy0CW7?p=preview
Update:
And you can use orderBy with ng-repeat as davidkonrad mentioned:
<table>
<tr>
<th ng-repeat="h in list[0].headers | orderBy: 'id'">{{h.name}}</th>
</tr>
<tr ng-repeat="record in list[0].records">
<th ng-repeat="cell in record.cells | orderBy: 'id'">{{cell.value}}</th>
</tr>
</table>
Adding something extra to Joe's answer. If you are planning to get the data from a separate JSON file, you can use the following code in your .js file.
(function () {
'use strict';
angular.module('plunker', [])
.controller('MainCtrl', MainCtrl);
MainCtrl.$inject = ['$scope', '$http'];
function MainCtrl($scope, $http) {
$http.get('[path to your JSON file]/data.json').success(function (data) {
$scope.list= data;
});
}
})();
I'm trying to figure out how to dynamically show a table with a JSON element but in a format that is hard to do with tables. I'm using AngularJs 1.6.4 and Bootstrap but I'm kind of new at Angular. My JSON:-
"foo": {
"name": "foo",
"displayName": "FOO SHOW",
"environments": [
{
"id": "one",
"name": "PROD",
"url": "http://my-prod-url.com"
},
{
"id": "two",
"name": "QA",
"url": "http://my-qa-url.com"
},
{
"id": "three",
"name": "DEV",
"url": "http://my-dev-url.com"
}
]
},
"bar": {
"name": "bar",
"displayName": "BAR SHOW",
"environments": [
{
"id": "four",
"name": "PROD",
"url": "https://my-prod2-url.com"
},
{
"id": "five",
"name": "QA",
"url": "https://my-uat2-url.com"
},
{
"id": "six",
"name": "DEV",
"url": "https://my-dev2-url.com"
}
]
}
I want to display this in a way that dynamically shows everything but based on application on the top and environment on the left of a table. For example:-
ENV | FOO | BAR
PROD| fooProdUrl| barProdUrl
QA | fooQaUrl| barQaUrl
DEV | fooDevUrl| barDevUrl
I've tried this but it's not dynamic and it doesn't display in the order I want:-
<table class="table">
<thead>
<tr>
<th class="text-center">Environment</th>
<th class="text-center" data-ng-repeat="list in applications">{{list.displayName}}</th>
</tr>
</thead>
<tbody class="text-center">
<tr data-ng-repeat="list in applications">
<th class="text-center">
{{list.environments[0].name}} and {{list.name}}
</th>
<td>
{{list.environments[0].url}} and {{list.name}} and {{list.environments[0].name}}
</td>
<td>
{{list.environments[1].url}} and {{list.name}} and {{list.environments[1].name}}
</td>
</tr>
</tbody>
</table>
This displays it in rows but not in the column way I want it.
Should I reorganize my JSON object? Split it in a different way? I've been stuck for a little bit on this.
Thanks!
I have an object that looks like this:
{
"10": {},
"12": {
"20": {
"value": 1,
"id": 1,
},
"100": {
"value": 12,
"id": 1,
}
},
"14": {
"100": {
"value": 14,
"id": 2,
}
},
"16": {},
"18": {},
"20": {
"100": {
"value": 23,
"id": 1,
},
"150": {
"value": 56,
"id": 3,
}
},
"22": {},
"24": {},
"26": {
"50": {
...
I want to create a table based on this object that should be like this:
I am not sure how to create this table though, by using the correct combination of repeats. I am currently trying at this:
<table>
<thead>
<tr>
<th>type</th>
<th>module</th>
<th>value</th>
<th>id</th>
</tr>
</thead>
<tbody>
<tr ng-repeat-start="(row1, value1) in TestData">
<td rowspan="{{value1.length}}">{{row1}}</td>
<td ng-repeat="(label2, value2) in value1">{{label2}}</td>
</tr>
</tbody>
</table>
At first sight, you could do something like that by inserting a <tbody> (more information here: Angular.js ng-repeat across multiple tr's)
var myAppModule = angular.module('myApp', []).controller('MyController', MyController);
function MyController() {
// https://stackoverflow.com/questions/1345939/how-do-i-count-a-javascript-objects-attributes
this.objectCount = function(obj) {
return Object.keys(obj).length;
}
this.data = {
"10": {},
"12": {
"20": {
"value": 1,
"id": 1,
},
"100": {
"value": 12,
"id": 1,
},
"200": {
"value": 120,
"id": 10,
}
},
"14": {
"100": {
"value": 14,
"id": 2,
}
},
"16": {},
"18": {},
"20": {
"100": {
"value": 23,
"id": 1,
},
"150": {
"value": 56,
"id": 3,
}
},
"22": {},
"24": {}
};
}
table,
th,
td {
border: 1px solid black;
}
table {
border-collapse: collapse;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyController as ctrl">
<table>
<thead>
<tr>
<th>type</th>
<th>module</th>
<th>value</th>
<th>id</th>
</tr>
</thead>
<tbody ng-repeat="(row1, value1) in ctrl.data" ng-switch="ctrl.objectCount(value1) === 0">
<tr ng-switch-when="true">
<td>{{row1}}</td>
<td colspan="3"></td>
</tr>
<tr ng-switch-when="false" ng-repeat="(row2, value2) in value1">
<td ng-if="$index === 0" rowspan="{{ctrl.objectCount(value1)}}">
{{row1}}
</td>
<td>{{row2}}</td>
<td>{{value2.value}}</td>
<td>{{value2.id}}</td>
</tr>
</tbody>
</table>
</div>
If you need something more refined with merging of rows and columns, you should think to build a more oriented view objects, so that the template is simpler, and your business logic is in JavaScript.
I have the following code:
var dummyData = {
"activities": [
{ "date": "19/06/2015 19:00", "user": "Dan", "display": "First Item" },
{ "date": "19/06/2015 19:00", "user": "Andrew", "display": "Second Item" },
{ "date": "19/06/2015 19:00", "user": "Trevor", "display": "Third Item" },
{ "date": "19/06/2015 19:00", "user": "Bob", "display": "Fourth Item" }
]
};
$("#sysActTable").dataTable({
"data": dummyData.activities,
});
I have tried several variations but I am always getting the error that points to this page. My HTML is as follows:
<table id="sysActTable" class="table table-hover" style="margin-bottom:0px">
<thead>
<tr>
<th style="width:20%">Date</th>
<th style="width:30%">User</th>
<th style="width:50%">Display</th>
</tr>
</thead>
<tbody>
<tr>
<td style="width:20%"></td>
<td style="width:30%"></td>
<td style="width:50%"></td>
</tr>
</tbody>
again I have tried a number of varieties. Why am I getting this error below?
DataTables warning: table id=sysActTable - Requested unknown parameter '0' for row 0
The problem is that your data is an array of objects. By default, DataTables expects data to be an array of arrays.
You need to use columns.data option to describe your data structure.
$("#sysActTable").dataTable({
"data": dummyData.activities,
"columns": [
{ "data": "date" },
{ "data": "user" },
{ "data": "display" }
]
});