My json looks like this :
[{"Name":["A","B","C","D","E","F"], "Age":["20","30","40","50","55","60"], "Gender":["M","M","F","M","Unknown","Unknown"]}]
I want a table in angularjs similar to this
Name Age Gender
A 20 M
B 30 M
C 40 F
I could see many example when my json is similar to this :
[
{Name: "A", Age: "20", Gender: "M"},
{Name: "Bag", Age: "30", Gender: "F"},
{Name: "Pen", Age: "40", Gender: "F"}
];
But I don't know how to proceed with my json. Could anyone help with this?
Assuming your property arrays all have the same number of elements (and are properly arranged) you could use the $index of ng-repeat.
<table>
<thead>
<tr>
<td>Name</td>
<td>Age</td>
<td>Gender</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="name in obj.Name">
<td>{{name}}</td>
<td>{{obj.Age[$index]}}</td>
<td>{{obj.Gender[$index]}}</td>
</tr>
</tbody>
</table>
Alternatively (using the same assumption that the data is well-formed), you can just use javascript to consolidate the three separate lists into a single list of person objects. Then you can proceed like the other examples you've seen.
Javascript might look something like this:
$scope.people = [];
obj.Name.forEach(function(name, index) {
people.push(
{
Name: name,
Gender: obj.Gender[index],
Age: obj.Age[index]
});
});
Then a simple ng-repeat on the new people array will work.
...
<tbody>
<tr ng-repeat="person in people">
<td>{{person.Name}}</td>
<td>{{person.Age}}</td>
<td>{{person.Gender}}</td>
</tr>
</tbody>
Try something.
<div ng-repeat="user in users.Name">
Name : {{user}} Age : users.Age[$index] Gender : users.Gender[$index]
</div>
I assume your object is sequenced and arranged
Use lodash _.zip function to arrange them in array, and _.map to convert it to json objects using custom function:
var rows = _.zip(users.Name, users.Age, users.Gender); // [["A",20,"M"],...]
$scope.users =
_.map(rows, function(row) {
return {Name: row[0], Age: row[1], Gender: row[2]}
});
and then iterate them getting values:
<table ng-controller="UsersTableController">
<thead>
<th>NAME</th>
<th>AGE</th>
<th>GENDER</th>
</thead>
<tbody>
<tr ng-repeat="user in users">
<td>{{user.Name}}</td>
<td>{{user.Age}}</td>
<td>{{user.Gender}}</td>
</tr>
</tbody>
</table>
reference: https://lodash.com/docs#zip , https://lodash.com/docs#map
Related
How do I stop default sorting inside the ng-repeat for dynamic table data ?
Currently I am getting below order:
Addr | CustomerId | Name
but what I want is below ordering:
CustomerId | Name | Addr
Any Help would me much appreciated.
JS:
app.controller('MyController', function ($scope) {
$scope.Customers = [
{ CustomerId: 1, Name: "John Hammond", Addr:'India'
},
{
CustomerId: 2, Name: "Mudassar Khan", Addr:'India'
},
{
CustomerId: 3, Name: "Suzanne Mathews", Addr:'India'
},
{
CustomerId: 4, Name: "Robert Schidner", Addr: 'India'
}
];
});
HTML:
<table>
<tr >
<th ng-repeat="(key,value) in Customers[0]">{{key}}</th>
</tr>
<tbody ng-repeat="c in Customers">
<tr>
</tr>
</tbody>
</table>
Try this below way. I hope this below snippet result is showing what you want.
angular.module("aaa",[]).controller('MyController', function ($scope) {
$scope.Customers = [
{ CustomerId: 1, Name: "John Hammond", Addr:'India'
},
{
CustomerId: 2, Name: "Mudassar Khan", Addr:'India'
},
{
CustomerId: 3, Name: "Suzanne Mathews", Addr:'India'
},
{
CustomerId: 4, Name: "Robert Schidner", Addr: 'India'
}
];
$scope.keys = Object.keys($scope.Customers[0]);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="aaa" ng-controller="MyController">
<table>
<tr>
<th ng-repeat="key in keys">
{{key}}
</th>
</tr>
<tbody ng-repeat="c in Customers">
<tr>
<td ng-repeat="key in keys">{{c[key]}}</td>
</tr>
</tbody>
</table>
</div>
So objects in JS are inherently unordered. What you can do is just hard code the keys in the header if that will be fixed for that particular table and then print the values in the respective order.
Something like this:
<table>
<tr >
<th>CustomerId</th>
<th>Name</th>
<th>Addr</th>
</tr>
<tbody>
<tr ng-repeat="c in Customers">
<td>{{CustomerId}}</td>
<td>{{Name}}</td>
<td>{{c.Addr}}</td>
</tr>
</tbody>
</table>
Note: I put the ng-repeat on the tr which is probably what you need. I dont think you should put it on the tbody.
Do you mean the sort order of the data or the display order of the columns?
The accepted answer displays the data by the order of the columns as specified, but if you want the data itself sorted then just add a filter to the data like this:
<tbody ng-repeat="c in Customers|orderBy:['CustomerId','Name','Addr']">
This sorts the actual data in the list by the fields specified.
Okay, so I'm having hard time understanding how ng-repeat builds tables. What I'm trying to do is that per row, there is customer name and address. I can't get it to work. Here is my HTML code:
<table class="table table-striped" ng-controller="myController">
<thead>
<tr>
<th>Company Name</th>
<th>Address</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="company in fieldData" row-id="{{ company.name }}">
<td>{{ company.name }}</td><td>{{ company.address }}</td>
</tr>
</tbody>
</table>
and here is my script:
var companyName = [];
var companyAddress = [];
$scope.fieldData = [];
$(data).find('record').each(function () {
companyName.push($(this).record(6));
companyAddress.push($(this).record(47));
});
$scope.fieldData.push({
name: companyName,
address: companyAddress
})
So, in companyName and companyAddress arrays, there are name and addresses being stored. But I can't get one company & address per row. Any ideas?
You built an one element array with one object of two arrays, like:
fieldData: [
{
name: [
'name1', 'name2', 'etc'
],
address: [
'addr1', 'addr2', 'etc'
]
}
]
You want to have an array of objects with name and address fields:
fieldData: [
{
name: 'name1',
address: 'addr1'
},
{
name: 'name2',
address: 'addr2'
},
{
name: 'etc',
address: 'etc'
}
]
To achieve that, go with:
$scope.fieldData = [];
$(data).find('record').each(function (item) {
$scope.fieldData.push({
name: item.record(6),
address: item.record(47)
});
});
Please, how can we make the table below with ng-repeat? I do not have permission to change the json structure, so I have to use exactly this way.
My json:
$scope.carCollection = {
'Toyota': [
{
'model': 'Corolla',
'price': '20.000,00',
'tag': ['a', 'b']
},{
'name': 'Hilux',
'price': '31.000,00',
'tag': ['b', 'c']
}
],
'Honda': [
{
'model': 'Civic',
'price': '18.000,00',
'tag': ['c']
}
]
};
And this is the html table:
<table>
<tr>
<td>Producer</td>
<td>Model</td>
<td>Price</td>
<td>Tags</td>
</tr>
<tr>
<td>Toyota</td>
<td>Corolla</td>
<td>20.000,00</td>
<td>a b</td>
</tr>
<tr>
<td>Toyota</td>
<td>Hilux</td>
<td>31.000,00</td>
<td>b c</td>
</tr>
<tr>
<td>Honda</td>
<td>Civic</td>
<td>18.000,00</td>
<td>c</td>
</tr>
</table>
Thanks!!!
You can find the ng-repeat documentation
https://docs.angularjs.org/api/ng/directive/ngRepeat
$scope.friends =
[{name:'John', phone:'555-1212', age:10},
{name:'Mary', phone:'555-9876', age:19},
{name:'Mike', phone:'555-4321', age:21},
{name:'Adam', phone:'555-5678', age:35},
{name:'Julie', phone:'555-8765', age:29}];
<div ng-controller="ExampleController">
<table class="friend">
<tr>
<th>Name</th>
<th>Phone Number</th>
<th>Age</th>
</tr>
<tr ng-repeat="friend in friends">
<td>{{friend.name}}</td>
<td>{{friend.phone}}</td>
<td>{{friend.age}}</td>
</tr>
</table>
You can format your data into your controller before render it in your view. Moreover, in my example you will see the :: bindings.
This is the one-time binding, it will stop recalculating the expression once they are stable, so you can improve your page loading by reducing numbers of watchers.
Controller
(function(){
function Controller($scope) {
$scope.carCollection = {
'Toyota': [
{
'model': 'Corolla',
'price': '20.000,00',
'tag': ['a', 'b']
},{
'model': 'Hilux',
'price': '31.000,00',
'tag': ['b', 'c']
}
],
'Honda': [
{
'model': 'Civic',
'price': '18.000,00',
'tag': ['c']
}
]
};
//To format our data
function format(data){
//Return a flatten array
return [].concat.apply([], Object.keys(data).map(function(key){
//Map our data object
return data[key].map(function(elm){
//Add brand property with the current key
elm.brand = key;
//Join tag array value
elm.tag = elm.tag.join(' ');
return elm;
});
}));
}
//Apply our format function
$scope.carCollection = format($scope.carCollection);
}
angular
.module('app', [])
.controller('ctrl', Controller);
})();
Then, you will get a flat array, so you just can iterate over it.
HTML
<body ng-app='app' ng-controller='ctrl'>
<table>
<tr>
<td>Producer</td>
<td>Model</td>
<td>Price</td>
<td>Tags</td>
</tr>
<tr ng-repeat="item in ::carCollection">
<td>{{::item.brand}}</td>
<td>{{::item.model}}</td>
<td>{{::item.price}}</td>
<td>{{::item.tag}}</td>
</tr>
</table>
</body>
You can see the Working Plunker
I have some data that has the following format:
[name:'Name1', speed:'Val1', color:'Val2']
[name:'Name2', speed:'Val4', color:'Val5']
[name:'Name3', speed:'Val6', color:'Val7']
That I want to display in a table like this:
|Name1|Name2|Name3|
______|_____|______
speed |Val1 |Val4 |Val6
color |Val2 |Val5 |Val7
What I tried to do is group my data like this in the controller:
$scope.data = {
speeds: [{
...
},{
...
},{
...
}],
colors: [{
...
},{
...
},{
...
}],
};
But I am not sure what to put inside the empty areas, because all values there represent the values of the 'val1' variable for all Names (Accounts), and my tests until now keep failing.
You can imagine this as some sort of a comparisons matrix, that is used in order to see the all the values of the same variable across different accounts.
How can I represent the data in my model in order for me to successfully display them in a table as explained?
Edit
My difficulty lies in the fact that you create a table by going from row to row, so my html looks something like this:
<table md-data-table class="md-primary" md-progress="deferred">
<thead>
<tr>
<th ng-repeat="header in headers">
{{header.value}}
</th>
</tr>
</thead>
<tbody>
<tr md-auto-select ng-repeat="field in data">
<td ng-repeat="var in field">{{var.value}}</td>
</tr>
</tbody>
</table>
So as you can see I have a loop for each row, and a loop for each value of each row. This would be easier if I wanted to display the data horizontally, but I want the data vertically. So if we where talking about cars, we would have the car models as headers, and their respective characteristics(speed, color, etc) in each row.
If this is your basic structure:
var cols = [{name:'Name1', val1:'Val1', val2:'Val2'},
{name:'Name2', val1:'Val4', val2:'Val5'},
{name:'Name3', val1:'Val6', val2:'Val7'}];
This code
$scope.table = cols.reduce(function(rows, col) {
rows.headers.push({ value: col.name });
rows.data[0].push({ value: col.speed });
rows.data[1].push({ value: col.color });
return rows;
}, {headers:[], data:[[], []]});
will give you this structure for $scope.table:
$scope.table = {
headers : [{
value : "Name1"
}, {
value : "Name2"
}, {
value : "Name3"
}
],
data : [
[{
value : 'val1'
}, {
value : 'val4'
}, {
value : 'val6'
}
],
[{
value : 'val2'
}, {
value : 'val5'
}, {
value : 'val17'
}
]
]
};
<table md-data-table class="md-primary" md-progress="deferred">
<thead>
<tr>
<th ng-repeat="header in table.headers">
{{header.value}}
</th>
</tr>
</thead>
<tbody>
<tr md-auto-select ng-repeat="field in table.data">
<td ng-repeat="var in field">{{var.value}}</td>
</tr>
</tbody>
</table>
You could try this:
HTML
<table ng-app="myTable" ng-controller="myTableCtrl">
<thead>
<tr>
<th ng-repeat="car in cars">{{car.name}}</th>
</tr>
</thead>
<tbody>
<tr>
<td ng-repeat="car in cars">{{car.speed}}</td>
</tr>
<tr>
<td ng-repeat="car in cars">{{car.color}}</td>
</tr>
</tbody>
</table>
JS
angular.module("myTable",[])
.controller("myTableCtrl", function($scope) {
$scope.cars = [
{
name:'Name1',
speed:'Val1',
color:'Val2'
},
{
name:'Name2',
speed:'Val4',
color:'Val5'
},
{
name:'Name3',
speed:'Val6',
color:'Val7'
}
]
});
https://jsfiddle.net/ABr/ms91jezr/
I have a table with some data to view in html. when i do click print, i need to get all the data from db and print it. I am getting the data and populating the model data when i click on print, only the model is updated and print shows the old data. In the code below, newitems is not added to items when i click on print.
http://jsfiddle.net/vijaivp/Y3BJa/306/
HTML
<div ng-app>
<div class="hidden-print" ng-controller="PrintCtrl">
<br />
<div id="overallPrint" class='visible-print' style="float:left; margin-right:50px;">
<h4>Overall Report</h4>
<table border="1">
<thead>
<tr>
<td>Name</td>
<td>Price</td>
<td>Quantity</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in items">
<td>{{item.Name}}</td>
<td>{{item.Price}}</td>
<td>{{item.Quantity}}</td>
</tr>
</tbody>
</table>
<br>
<input type="button" value="Print Overall" ng-click='printOverallReport()' />
</div>
</div>
</div>
JS
function PrintCtrl($scope, $window, $q) {
$scope.items = [
{Name: "Soap", Price: "25", Quantity: "10"},
{Name: "Shaving cream", Price: "50", Quantity: "15"}
];
$scope.newitems = [
{Name: "Shampoo", Price: "100", Quantity: "5"}
];
$scope.printOverallReport = function () {
$scope.items.push($scope.newitems[0]);
$window.print();
};
}
Using a timeout with Angular's $timeout service will fix it:
function PrintCtrl($scope, $window, $q, $timeout) {
$scope.items = [
{Name: "Soap", Price: "25", Quantity: "10"},
{Name: "Shaving cream", Price: "50", Quantity: "15"}
];
$scope.newitems = [
{Name: "Shampoo", Price: "100", Quantity: "5"}
];
$scope.printOverallReport = function () {
$scope.items = $scope.newitems;
console.log($scope.items.length);
$timeout($window.print, 0);
console.log($scope.items.length);
};
}
Fiddle
For a comprehensive explanation as to why, please see DVK's answer (2nd one) here: Why is setTimeout(fn, 0) sometimes useful?
TL:DR;
When you call $window.print() the old HTML is still present since the browser hasn't rendered it yet. It's waiting to finish the javascript function run. setting a $timeout 0 will queue the print at the end of execution queue and will guarantee it happens after the HTML has been rendered. (I still strongly recommend to read his answer)