I have a scope array
$scope.myArr = [{'id':'1','vehicle':'car'},{'id':'1','vehicle':'bike'}]
I need to show this data in my html page as below
|id|vehicle|
|--|-------|
|1 |car |
|2 |bike |
Is there any way I can achieve this.
Use ng-repeat like this,
<tr>
<th ng-repeat="(key, val) in myArr[0]">{{ key }}</th>
</tr>
<tr ng-repeat="row in myArr">
<td ng-repeat="column in row">
{{ column }}
</td>
</tr>
DEMO
angular.module('myApp', [])
.controller('myController', function($scope) {
$scope.myArr = [{'id':'1','vehicle':'car'},{'id':'1','vehicle':'bike'}]
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body ng-app="myApp">
<table ng-controller="myController" border="1">
<tr>
<th ng-repeat="(key, val) in myArr[0]">{{ key }}</th>
</tr>
<tr ng-repeat="row in myArr">
<td ng-repeat="column in row">
{{ column }}
</td>
</tr>
</table>
</body>
Related
I want to change the number of columns on modifying a boolean variable.
Check my example (in plnkr):
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ngSanitize', 'ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('myCtrl', function($scope, $log) {
$scope.debug = {};
$scope.fields = [{
header: "first",
hideField: !$scope.debug.flag
},
{
header: "second"
},
{
header: "third"
},
{
header: "fourth"
},
];
$scope.entries = [{
first: "hello1",
second: "hello2",
third: "hello3",
fourth: "hello4"
}, ]
$scope.myBool = true;
});
<!doctype html>
<html ng-app="ui.bootstrap.demo">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-animate.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-sanitize.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.5.0.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="myCtrl">
<button id="testButton" class='btn btn-danger' ng-click='debug.flag = !debug.flag'><i class="glyphicon glyphicon-hand-right"></i> refreshFields! debug.flag = {{!!debug.flag}}</button>
<hr>
<h2 class="label label-info">table 1 with property.hideField = true</h2>
<table class="table table-hover">
<tr>
<!-- Headers of list-->
<th ng-repeat="property in fields" ng-if="!property.hideField">{{property.header}}
</th>
</tr>
<tbody>
<tr ng-repeat="entry in entries">
<td ng-repeat="property in fields" ng-if="!property.hideField">
{{entry[property.header]}} {{!!debug.flag}}
</td>
</tr>
</tbody>
</table>
<h4 class="label label-info">table 2 with ng-if => property.hideField = false</h4>
<table class="table table-hover">
<tr>
<!-- Headers of list-->
<th ng-repeat="property in fields" ng-if="property.hideField">{{property.header}}
</th>
</tr>
<tbody>
<tr ng-repeat="entry in entries">
<td ng-repeat="property in fields" ng-if="property.hideField">
{{entry[property.header]}} {{!!debug.flag}}
</td>
</tr>
</tbody>
</table>
<h2 class="label label-info">table 3 without ng-if</h2>
<table class="table table-hover">
<tr>
<!-- Headers of list-->
<th ng-repeat="property in fields">{{property.header}}
</th>
</tr>
<tbody>
<tr ng-repeat="entry in entries">
<td ng-repeat="property in fields">
{{entry[property.header]}} {{!!debug.flag}}
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
How to reproduce it:
Click on the red button and the flag will toggle from false to true.
Expected behavior:
Table 1 starts with 3 columns. It should show four after clicking.
Table 2 starts with 1 column. It should show 0 columns after clicking.
Table 3 is just a control table with all the data.
Your heading would become visible if you modified the value of its hideField property. But you're not doing that. You're modifying the value of $scope.debug.flag.
The fact that hideField was initialized with the value of $scope.debug.flag won't magically change hideField every time you change $scope.debug.flag.
Just like if you do
var a = 1;
var b = a;
a = 42;
The value of b will still be 1. Not 42.
Changing the value of $scope.debug.flag won't change the value of hideField. Because, it has already been initialized at the time of controller load. The workaround you can apply here is bind that hideField to a method and evaluate that in your ng-if. Sample below.
JS:
$scope.fields = [{
header: "first",
hideField: function() {
return !$scope.debug.flag;
}
}, {
header: "second"
}, {
header: "third"
}, {
header: "fourth"
}, ];
HTML:
<h2 class="label label-info">table 1 with property.hideField = true</h2>
<table class="table table-hover">
<tr>
<!-- Headers of list-->
<th ng-repeat="property in fields" ng-if="!property.hideField()">{{property.header}}
</th>
</tr>
<tbody>
<tr ng-repeat="entry in entries">
<td ng-repeat="property in fields" ng-if="!property.hideField()">
{{entry[property.header]}} {{!!debug.flag}}
</td>
</tr>
</tbody>
</table>
This is not a clean solution though. But, still will solve your problem.
I have an API which return me a JSON array:
{"i":11,"j":12,"iterationNumber":9,"results":[12,6,3,10,5,16,8,4,2,1]}
How can I make a table in angular, so the data is displayed correctly?
Currently I have this:
My html code is:
<table class="table table-striped " ng-show="tableR">
<thead>
<tr>
<th>i Value</th>
<th>j Value</th>
<th>iternation Number Value</th>
<th>results</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="x in data">
<td>{{x.i}}</td>
<td>{{x.j}}</td>
<td>{{x.iterationNumber}}</td>
<td>{{x.results}}</td>
</tr>
</tbody>
</table>
Can you help me fix the last column, so instead of displaying all the values in one row, make it display it into different rows?
I believe this might be closer to what Angel Silva is after.
HTML:
<body ng-controller="MainCtrl">
<table class="table table-striped">
<thead>
<tr>
<th>i Value</th>
<th>j Value</th>
<th>iternation Number Value</th>
<th>results</th>
</tr>
</thead>
<tbody ng-repeat="x in data">
<tr ng-repeat="r in x.results">
<td>{{x.i}}</td>
<td>{{x.j}}</td>
<td>{{x.iterationNumber}}</td>
<td>{{r}}</td>
</tr>
</tbody>
</table>
</body>
JavaScript/AngularJS:
app.controller('MainCtrl', function($scope) {
$scope.data = [{"i":11,"j":12,"iterationNumber":9,"results":[12,6,3,10,5,16,8,4,2,1]}];
});
Here's a link to a working Plunker, http://plnkr.co/edit/NrnFI17P932KckzXRcF4?p=preview
Use a second ng-repeat within an <ul> (unordered list):
<table class="table table-striped " ng-show="tableR">
<thead>
<tr>
<th>i Value</th>
<th>j Value</th>
<th>iternation Number Value</th>
<th>results</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="x in data">
<td>{{x.i}}</td>
<td>{{x.j}}</td>
<td>{{x.iterationNumber}}</td>
<td>
<ul>
<li ng-repeat="r in x.results">
{{ r }}
</li>
</ul>
</td>
</tr>
</tbody>
</table>
You could create an array of columns which could be named as columns. Loop over columns to render td's data with current x
Controller
$scope.data = {"i":11,"j":12,"iterationNumber":9,"results":[12,6,3,10,5,16,8,4,2,1]};
$scope.columns = Object.key($scope.data)
Markup
<tr ng-repeat="x in data">
<td ng-repeat="column in columns">{{x[column]}}</td>
</tr>
You can try array.join() method to join all the elements of an array into a string.
DEMO
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl',function($scope) {
$scope.tableR = true;
$scope.data = [{
"i":11,
"j":12,
"iterationNumber":9,
"results":[12,6,3,10,5,16,8,4,2,1]
}];
});
tr,th,td {
border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<table class="table table-striped " ng-show="tableR">
<thead>
<tr>
<th>i Value</th>
<th>j Value</th>
<th>iternation Number Value</th>
<th>results</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="x in data">
<td>{{x.i}}</td>
<td>{{x.j}}</td>
<td>{{x.iterationNumber}}</td>
<td>{{x.results.join()}}</td>
</tr>
</tbody>
</table>
</div>
API is connected well and showing display data, now facing the issue of formatting data into table.
using ng-repeat="item in items",
if use in tr then only 1 row shows, if using in tbody, then its repeats tbody.
HTML code
<tbody ng-repeat="item in itemsc">
<tr >
<th width="15%">Country</th>
<td width="85%">{{item.name}}</td>
</tr>
<tr>
<th>Flag</th>
<td>
<img ng-src="/assets/images/f/{{item.iso2 | lowercase}}.png" />
</td>
</tr>
<tr>
<th>Capital</th>
<td>{{item.capital}}</td>
</tr>
<tr>
<th>Region</th>
<td>{{item.region}}</td>
</tr>
<tr>
<th>Region</th>
<td>{{item.subRegion}}</td>
</tr>
<tr>
<th>GPS</th>
<td>Latitude: {{item.latitude}} | Longitude: {{item.longitude}}</td>
</tr>
</tbody>
Keep the data format like this.
Country,Flag,Catpital,Region,GPS are static.
> -------------------------------
| Country | Value |
> -------------------------------
| Flag | Value |
> -------------------------------
| Catpital | Value |
> -------------------------------
| Region | Value |
> -------------------------------
| GPS | Value |
> -------------------------------
Code snippet added below: Please have a look at angular code, and way it is implemented in a table. Cheers.!
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<script type="text/javascript">
angular.module("todoApp", [])
.controller("MainController", function($scope){
$scope.Products = [];
for(var i = 0; i < 3; i++)
{
var app = {
ProductId: i,
ProductName: 'ProductName' + (i + 1),
ProductCategory: 'ProductCategory' + (i + 1)
};
$scope.Products.push(app);
}
});
</script>
</head>
<body ng-app="todoApp">
<div ng-controller="MainController">
<table>
<tbody ng-repeat="product in Products">
<tr>
<td>
<div style="padding-bottom: 10px;">
<table border="1" cellpadding="2">
<tr>
<td>Sr.No</td>
<td>{{$index + 1}}</td>
</tr>
<tr>
<td>Product Name</td>
<td>{{product.ProductName}}</td>
</tr>
<tr>
<td>Product Category</td>
<td>{{product.ProductCategory}}</td>
</tr>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
Try moving ng-repeat="item in itemsc" from tbody to tr.
This should probably solve your problem.
Ideally the format should be as:
<table>
<thead>
<tr>
<td>Sr.#</td>
<td>Name</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="prop in Properties">
<td>{{$index + 1}}</td>
<td>{{prop.Name}}</td>
</tr>
</tbody>
</table>
According to your requirement the easy way to do this is changing the object structure you are passing to the list (itmes)
eg.
[{
"column1Value": "Country",
"column2Value": "Value"
}, {
"column1Value": "Flag",
"column2Value": "Value"
}, {
"column1Value": "Capital",
"column2Value": "Value"
}, {
"column1Value": "Region",
"column2Value": "Value"
}, {
"column1Value": "GPS",
"column2Value": "Value"
}]
When i am using ng-if with a flag and list contains some values:
<tr ng-if="flag" ng-repeat="x in list1">
{{"print a"}}
<!-- do something -->
</tr>
<tr ng-if="!flag" ng-repeat="x in list2">
{{"print b"}}
<!-- do something -->
</tr>
It is printing both a and b irrespective of flag.It should only print a and b based on flag value?
Here you go..
var app = angular.module('myApp',[])
.controller('myCtrl',function($scope){
$scope.flag = true;
$scope.list1 = [10,20,30,40,50];
$scope.list2 = [10,20,30,40,50];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<table ng-app="myApp" ng-controller="myCtrl">
<tr ng-if="flag" ng-repeat="x in list1">
<td>
{{"print a"}}
</td>
</tr>
<tr ng-if="!flag" ng-repeat="x in list2">
<td>
{{"print b"}}
</td>
</tr>
</table>
So, it does work.
I'm loading a large amount of data using ng-include.
I'd like to know if there is a way to know when a template is "rendered", because sometimes it seems like it's been "frozen", because I want to do a "loading screen" or something.
Thx.
Here's the code
controller code:
$scope.layout = {
current: 'single-table.html'
};
$scope.layout.get = function() {
return $scope.layout.current;
};
templates:
main.html
<div class="btn-group">
<button ng-click="layout.current = 'single-table.html'">Single</button>
<button ng-click="layout.current = 'multiple-table.html'">Multiple</button>
</div>
<div ng-include="layout.get()"></div>
single-table.html
<table class="table table-bordered">
<thead>
<th ng-repeat="column in columns">{{ column.title }}</th>
</thead>
<tbody>
<tr ng-repeat="record in records">
<td ng-repeat="field in record.fields"
ng-controller="FieldController"
ng-class="getClass()">
{{ field.display }}
</td>
</tr>
</tbody>
</table>
multiple-table.html
<table class="table table-bordered" ng-repeat="record in records">
<tbody>
<tr ng-repeat="field in record.fields">
<th>{{ columns[$index].title }}</th>
<td ng-controller="FieldController" ng-class="getClass()">
{{ field.display }}
</td>
</tr>
</tbody>
</table>
EDIT
I'm using version 1.2.0
One solution (probably not the best) is doing this (no ng-include)
<table class="table table-bordered" ng-show="layout.current == 'single-table.html'">
<thead>
<th ng-repeat="column in columns">{{ column.title }}</th>
</thead>
<tbody>
<tr ng-repeat="record in records">
<td ng-repeat="field in record.fields"
ng-controller="FieldController"
ng-class="getClass()">
<span lud-run="{{ field.ng_directive }}"></span>
</td>
</tr>
</tbody>
</table>
<table class="table table-bordered" ng-repeat="record in records" ng-show="layout.current == 'multiple-table.html'">
<tbody>
<tr ng-repeat="field in record.fields">
<th>{{ columns[$index].title }}</th>
<td ng-controller="FieldController" ng-class="getClass()">
<span lud-run="{{ field.ng_directive }}"></span>
</td>
</tr>
</tbody>
</table>
I have only 20 records, but (is not in the code), each cells loads a custom directive depends on the data type (string, date, datetime, image...). This "solution" I think runs the same data twice (ng-show, not ng-if), but when a switch the layout mode there is no "lag".
You can use the onload hook on ng-include to update a variable when the include has finished rendering. If you set it to true on clicking your button, then revert it back to false in onload, you should be able to leverage it to temporarily display a loading screen.