Angular: ng-repeat displaying order in a table - angularjs

I have an specific requirement where the json data comes like this:
[{Id : "a", Name : "John", age : 50},
{Id : "b", Name : "Bob", age : 40}]
I want to show it in a table using ng-repeat, but in a way where headers come in the first column, as below:
<table>
<tr>
<td>Id</td>
<td>a</td>
<td>b</td>
</tr>
<tr>
<td>Name</td>
<td>John</td>
<td>Bob</td>
</tr>
<tr>
<td>Age</td>
<td>50</td>
<td>40</td>
</tr>
</table>
Is there a way to achieve this using angularjs?
Thanks

Provided you have a controller:
angular.module('MyApp', [])
.controller('MyController', function($scope) {
$scope.data = [
{Id : "a", Name : "John", age : 50},
{Id : "b", Name : "Bob", age : 40}
];
});
Your markup would then be as follows. If the data isn't going to change after it is displayed:
<table>
<tr>
<td>Id</td>
<td ng-repeat="item in ::data">{{::item.Id}}</td>
</tr>
<tr>
<td>Name</td>
<td ng-repeat="item in ::data">{{::item.Name}}</td>
</tr>
<tr>
<td>Age</td>
<td ng-repeat="item in ::data">{{::item.age}}</td>
</tr>
</table>
If the data is going to change after it is displayed, and you want the view to update accordingly, then:
<table>
<tr>
<td>Id</td>
<td ng-repeat="item in data track by $index">{{item.Id}}</td>
</tr>
<tr>
<td>Name</td>
<td ng-repeat="item in data track by $index">{{item.Name}}</td>
</tr>
<tr>
<td>Age</td>
<td ng-repeat="item in data track by $index">{{item.age}}</td>
</tr>
</table>

You can convert your array in an object, then you can use nested ng-repeats in view, as below:
(function() {
"use strict";
angular.module('app', [])
.controller('mainCtrl', function($scope) {
var array = [
{
"Id":"a",
"Name":"John",
"age":50
},
{
"Id":"b",
"Name":"Bob",
"age":40
}
];
// If you're sure that the properties are always these:
$scope.mainObj = {
"Id": [],
"Name": [],
"age": []
};
// If you're unsure what are the properties:
/*
$scope.mainObj = {};
Object.keys(array[0]).forEach(function(value) {
$scope.mainObj[value] = [];
});
*/
// Iterates over its properties and fills the arrays
Object.keys($scope.mainObj).forEach(function(key) {
array.map(function(value) {
$scope.mainObj[key].push(value[key]);
})
});
});
})();
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
</head>
<body ng-controller="mainCtrl">
<table>
<tr ng-repeat="(key, values) in mainObj track by $index">
<td ng-bind="key"></td>
<td ng-repeat="value in values track by $index" ng-bind="value"></td>
</tr>
</table>
</body>
</html>
I hope it helps!

Related

How to use Nested ng-repeat to repeat table columns dynamically?

I want to make dynamic columns of a table and create a new object to save it in mongoDb.
I have first Array of Student as:
students = [{id: "1", name: "abc"},{id: "2", name: "def"},{id: "3", name: "hij"}]
and have second Array of Subjects as:
subjects = [{sName: "maths"},{sName: "science"}]
Here is the HTML
<div ng-app='t' ng-controller='test'>
<table>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th ng-repeat="subject in subjects">{{subject.sName}}</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in finalData track by $index">
<th><input type="text" ng-model="row.rollNo"/></th>
<th><input type="text" ng-model="row.fullName"></th>
<th ng-repeat="subject in subjects"><input type="text" ng-model="row.marks"></th>
<th>
<button ng-click="action($index)">
add/remove
</button></th>
</tr>
</tbody>
</table>
</div>
Here is the Controller
(function(){
var app = angular.module('t', []);
app.controller('test',
[
'$scope',
function($scope)
{
$scope.students = [{id: "1", name: "abc"},{id: "2", name: "def"},{id: "3", name: "hij"}]
$scope.subjects = [{sName: "maths"},{sName: "science"}]
$scope.finalData = new Array();
$scope.finalData.push({
icon : false
});
$scope.action=function(index){
if(index == $scope.finalData.length-1){
$scope.finalData[index].icon = true;
$scope.finalData.push({
icon : false
});
}else{
$scope.finalData.splice(index, 1);
}
};
}
]);
})();
The Output Looks like this.
The marks columns are repeating similar values. But i want one single finalObject to save my data.
Here is the jsFiddle of my problem https://jsfiddle.net/g8tn71tr/
The row subjects refer to the same NgModel row.marks which makes them have the same value.
You can solve it by making the ng-model refer to each of the subjects ng-model="row.marks[subject.sName]". This will result in that row.marks will become an object where each subject will be a key and the model will be in its value
(function(){
var app = angular.module('t', []);
app.controller('test',
[
'$scope',
function($scope)
{
$scope.students = [{id: "1", name: "abc"},{id: "2", name: "def"},{id: "3", name: "hij"}]
$scope.subjects = [{sName: "maths"},{sName: "science"}]
$scope.finalData = new Array();
$scope.finalData.push({
icon : false
});
$scope.action=function(index){
console.clear();
console.log($scope.finalData[index]);
if(index == $scope.finalData.length-1){
$scope.finalData[index].icon = true;
$scope.finalData.push({
icon : false
});
}else{
$scope.finalData.splice(index, 1);
}
};
}
]);
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app='t' ng-controller='test'>
<table>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th ng-repeat="subject in subjects">{{subject.sName}}</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in finalData track by $index">
<th><input type="text" ng-model="row.rollNo"/></th>
<th><input type="text" ng-model="row.fullName"></th>
<th ng-repeat="subject in subjects"><input type="text" ng-model="row.marks[subject.sName]"></th>
<th>
<button ng-click="action($index)">
add/remove
</button></th>
</tr>
</tbody>
</table>
</div>

How to update the number of columns in an angular table

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.

Angular js ng-repeat dynamic headers , avoid a column

On click of a button I get the following Response from Node JS .
[{
"_id": "590998cca8ac14d0c075282c",
"CompID": "0001388D",
"CompName": "ONE"
},
{
"_id": "590998cca8ac14d0c075282qc",
"CompID": "0001388D2",
"CompName": "TWO"
},
{
"_id": "590998cca8ac14d0c07528qq2c",
"CompID": "0001388D23",
"CompName": "Three"
}
]
I am printing this information using Angular JS table ng - repeat
This is my code
My question is , is it possible to skip _id field while printing ??
This is my code
<div ng-app="myapp" ng-controller="FirstCtrl">
<table border="1">
<tr>
<th ng-repeat="(key, val) in collectioninfo[0]">{{ key }}</th>
</tr>
<tr ng-repeat="row in collectioninfo">
<td ng-repeat="column in row">
{{ column }}
</td>
</tr>
</table>
</div>
JSFiddle
you can try with ng-if to avoid showing some elments in ng-repeat.
var myapp = angular.module('myapp', []);
myapp.controller('FirstCtrl', function($scope) {
$scope.collectioninfo = [{
"_id": "590998cca8ac14d0c075282c",
"CompID": "0001388D",
"CompName": "ONE"
},
{
"_id": "590998cca8ac14d0c075282qc",
"CompID": "0001388D2",
"CompName": "TWO"
},
{
"_id": "590998cca8ac14d0c07528qq2c",
"CompID": "0001388D23",
"CompName": "Three"
}
]
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="myapp" ng-controller="FirstCtrl">
<table border="1">
<tr>
<th ng-repeat="(key, val) in collectioninfo[0]" ng-if="key !== '_id'">{{ key }}</th>
</tr>
<tr ng-repeat="row in collectioninfo">
<td ng-repeat="(key2, val2) in row" ng-if="key2 !== '_id'">
{{ val2 }}
</td>
</tr>
</table>
</div>
Check the jsfiddle here
<table border="1">
<tr>
<th ng-repeat="(key, val) in collectioninfo[0]" ng-show="key != '_id'">{{ key }}</th>
</tr>
<tr ng-repeat="row in collectioninfo">
<td ng-repeat="column in row" ng-hide="column === row._id">
{{ column }}
</td>
</tr>
</table>
I have added a check for the key '_id'.
after you get the response in your angular controller do this :
$scope.datas = [];
//lines of code
.then(function success(response) {
$scope.collectionInfo=response.data.collectionInfo;
for(var i=0;i<$scope.collectionInfo.length;i++){
$scope.index=i;
$scope.datas.push($scope.collectionInfo[i]);
}
//lines of code
});
And on the html page do this :
<div id="DisplayCollection">
<table ng-repeat="x in collectionInfo">
<tr>
<th>
CompID
</th>
<th>
CompName
</th>
</tr>
<tr ng-repeat="y in x track by $index">
<td>{{y.compID[$index]}}</td>
<td>{{y.compName[$index]}}</td>
</tr>
</table>
Given that you have sent the data in form of an array: collectionInfo

AngularJS Table Custom Search Filter Per Column

I am looking for help in creating a custom filter that will work on any table that has a search property.
So far, I can get the table to filter based on what is input into each column search bar, but I can't figure out how to implement a 'startsWith' for each column as well so that it will only find 'Florida' if you type 'Flor' or 'Fl', etc. instead of finding it when typing 'lor' or 'ida'.
I have been able to get just one column working with a custom filter, but lost on how to implement this for multiple columns.
Here is the plunkr example: http://plnkr.co/edit/CE3uhZmksiepmVL2bLNF?p=preview
Script:
var app = angular.module("stateManagement", []);
app.controller("myCtrl", ["$scope", myCtrl]);
function myCtrl($scope) {
$scope.names = [{
Name: "Florida",
Country: "USA"
}, {
Name: "Texas",
Country: "USA"
}]
$scope.state = '';
$scope.elements = [{
state: "Florida"
}, {
state: "Texas"
}];
}
app.filter('myfilter', function() {
function strStartsWith(str, prefix) {
return (str.toLowerCase() + "").indexOf(prefix.toLowerCase()) === 0;
}
return function(items, state) {
var filtered = [];
angular.forEach(items, function(item) {
if (strStartsWith(item.state, state)) {
filtered.push(item);
}
});
return filtered;
};
});
Html:
<body ng-app='stateManagement' ng-controller='myCtrl'>
<div class="col-md-12">
<table class="table table-responsive">
<thead>
<tr>
<th>Name</th>
<th>Country</th>
</tr>
<tr>
<th><input class="form-control"
type="text"
placeholder="Search..."
ng-model="search.Name"/>
</th>
<th><input class="form-control"
type="text"
placeholder="Search..."
ng-model="search.Country"/>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="x in names | filter:search">
<td>{{ x.Name }}</td>
<td>{{ x.Country }}</td>
</tr>
</tbody>
</table>
</div>
<div class="col-md-12">
<input ng-model="state">
<table id="hotels">
<tr data-ng-repeat="element in elements | myfilter:state">
<td>{{element.state}}</td>
</tr>
</table>
<br/>
</div>
</body>
Thank you in advance for helping!

Add data into rows on click

I want that when I insert some data into a textbox and click a button, the data should be inserted in a particular table column, and when i keep on adding the data the rows should keep on increasing with the entered data. Code:
var parking = angular.module("parking", []);
parking.controller("parkingCtrl", function($scope){
$scope.carnamebind='';
$scope.car=[];
$scope.bindcarName = function(){
var ee=$scope.car;
ee.push($scope.carname);
$scope.carnamebind=ee;
}
})
the html:
<body ng-controller="parkingCtrl">
<h3 ng-model="appTitle"></h3>
<table>
<tr>
<td>Car name</td>
<td>Car model</td>
</tr>
<tr>
<td>{{carnamebind}}</td>
<td></td>
</tr>
<tr>
<td ><input type="text" ng-model="carname"/><input type="button" ng-click="bindcarName()"/></td>
<td></td>
</tr>
</table>
</body>
2 problems are coming:
1) All pushed data into array is inserted in the same column
2) Data is inserted in the form of array, like ["sd","sdasd"]
Thanks
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.carnamebind= [
"Alfreds Futterkiste",
"Berglunds snabbköp",
"Centro comercial Moctezuma",
"Ernst Handel",
];
$scope.bindcarName = function(ee){
$scope.carnamebind.push(ee);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html>
<body ng-app="myApp">
<table ng-controller="myCtrl" border="1">
<tr>
<td>Car name</td>
<td>Car model</td>
</tr>
<tr ng-repeat="x in carnamebind">
<td>{{x}}</td>
<td></td>
</tr>
<tr>
<td ><input type="text" ng-model="carname"/></td>
<td><input type="submit" ng-click="bindcarName(carname)"/></td>
</tr>
</table>
</body>
</html>

Resources