Pagination gets "stuck"? - angularjs

I have a simple table application that displays dummy data with columns like name, number, date, etc. You can sort it by columns, and it is paginated.
However, when I use the pagination, some of the rows get stuck at the top. It kind of gets sorted alphabetically by the column I intended, but when the page changes (pretend page 4), the rows underneath the first few top rows change, while the very top rows don't budge.
Here is a functional plunker:
HTML:
<pagination class="pagination pagination-sm" items-per-page="itemsPerPage" total-items="totalItems" ng-model="currentPage" ng-change="pageChanged()"></pagination>
<table class="table table-hover">
<tr>
<th ng-repeat="key in keys" ng-click="sorting.predicate=key;">
{{key}}
</th>
</tr>
<tr ng-repeat="row in data | startFrom:currentRow | orderBy:sorting.predicate:sorting.reverse | limitTo:itemsPerPage">
<td ng-repeat="key in keys">
{{row[key]}}
</td>
</tr>
</table>
Angular:
app.filter('startFrom', function () {
return function (input, start) {
start = +start;
return input.slice(start);
};
});
$scope.data = [{
"id": 0,
"age": 30,
"name": "Trina Pace",
"gender": "female",
"email": "trinapace#darwinium.com",
"phone": "+1 (874) 414-2654"
},etc..];
$scope.keys = Object.keys($scope.data[0]);
$scope.totalItems = $scope.data.length;
$scope.itemsPerPage = 25;
$scope.currentPage = 1;
$scope.currentRow = 0;
$scope.pageChanged = function () {
$scope.currentRow = ($scope.currentPage - 1) * $scope.itemsPerPage;
console.log('current row: ' + $scope.currentRow);
console.log('items per page: ' + $scope.itemsPerPage);
};
$scope.sorting = {predicate:'name',reverse:false};
Am I missing, and/or doing something incorrectly?

Move startFrom:currentRow to after orderBy:sorting.predicate:sorting.reverse.
You want to filter after you sort.

http://plnkr.co/edit/7BbgJ4TMU0pSY8gyDLef?p=preview
<table class="table table-hover">
<tr>
<th ng-repeat="key in keys" ng-click="sorting.predicate=key;">
{{key}}
</th>
</tr>
<tr ng-repeat="row in data | orderBy:sorting.predicate:sorting.reverse | startFrom:currentRow | limitTo:itemsPerPage">
<td ng-repeat="key in keys">
{{row[key]}}
</td>
</tr>
</table>

Related

How to display array in table using ng-repeat

Unlike other JSON data , I have simple arrays of two.
$scope.land = [ elephant, tiger, zebra ];
$scope.water = [ fish , octopus, crab];
I want to put up the array in table using ng-repeat. I tried this but data is not showing in proper format.
<table class="table table-dark">
<thead>
<tr>
<th scope="col">LAND</th>
<th scope="col">WATER</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="l in land track by $index">
<td>{{l}}</td>
<td>fish</td>
</tr>
</tbody>
</table>
EDIT:-
err in data showing vertical in table
enter image description here
new data :-
$scope.land = [ 'tiger in zoo', 'tiger in jungle', 'zebra'];
$scope.water = [ 'fish in pond'];
I think you are trying to display elements of two arrays next to each other (correct me if i'm wrong).
Here is a simple way to do that :
angular.module('myApp', [])
.controller('TestCtrl', function ($scope) {
$scope.land = [ 'tiger in zoo', 'tiger in jungle', 'zebra'];
$scope.water = [ 'fish in pond'];
$scope.combined = [];
var maxLength = ($scope.land.length > $scope.water.length) ? $scope.land.length : $scope.water.length;
//length is to be determined
for(var index = 0; index < maxLength ; index++) {
$scope.combined.push({
land: ($scope.land[index]) ? $scope.land[index] : '',
water: ($scope.water[index]) ? $scope.water[index] : ''
});
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="myApp" ng-controller="TestCtrl">
<table class="table table-dark">
<thead>
<tr>
<th scope="col">LAND</th>
<th scope="col">WATER</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in combined">
<td>{{item.land}}</td>
<td>{{item.water}}</td>
</tr>
</tbody>
</table>
</div>

How to collapse and hide in ng-repeat over table?

So I have a table where I need to show parent deals and on ng-show(clicking parent deal) I want to show child deals.
<table class="table table-hover">
<thead class="thead-dark">
<tr>
<th scope="col">Name</th>
<th scope="col">No_Of_Orders</th>
<th scope="col">Size</th>
<th scope="col">Book_Size</th>
<th scope="col">Remarks</th>
<th scope="col">Price_Guidance</th>
<th scope="col">CONTROL</th>
<th scope="col">Status</th>
<th scope="col">Current_Cut_Off</th>
<th scope="col">Tenor</th>
<th scope="col">Book</th>
<th scope="col">ORDCOLUMN</th>
<th scope="col">PKEY</th>
<th scope="col">Save</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="parentDeal in parentDeals track by $index" ng-click="childShow(parentDeal.PKEY)">
<td>{{parentDeal.Name}}</td>
<td>{{parentDeal.No_Of_Orders}}</td>
<td>{{parentDeal.Size}}</td>
<td>{{parentDeal.Book_Size}}</td>
<td>{{parentDeal.Remarks}}</td>
<td>{{parentDeal.Price_Guidance}}</td>
<td>{{parentDeal.CONTROL}}</td>
<td>{{parentDeal.Status}}</td>
<td>{{parentDeal.Current_Cut_Off}}</td>
<td>{{parentDeal.Tenor}}</td>
<td>{{parentDeal.Book}}</td>
<td>{{parentDeal.ORDCOLUMN}}</td>
<td>{{parentDeal.PKEY}}</td>
<td>{{parentDeal.Save}}</td>
<tr ng-repeat="childDeal in childDeals track by $index" ng-show = "childRowShow_{{childDeal.PKEY}}">
<td>{{childDeal.Name}}</td>
<td>{{childDeal.No_Of_Orders}}</td>
<td>{{childDeal.Size}}</td>
<td>{{childDeal.Book_Size}}</td>
<td>{{childDeal.Remarks}}</td>
<td>{{childDeal.Price_Guidance}}</td>
<td>{{childDeal.CONTROL}}</td>
<td>{{childDeal.Status}}</td>
<td>{{childDeal.Current_Cut_Off}}</td>
<td>{{childDeal.Tenor}}</td>
<td>{{childDeal.Book}}</td>
<td>{{childDeal.ORDCOLUMN}}</td>
<td>{{childDeal.PKEY}}</td>
<td>{{childDeal.Save}}</td>
</tr>
</tr>
</tbody>
</table>
This is the basic data:-
$scope.allDeals = [
{
"ORDCOLUMN":"2017-11-17T05:00:00.000000000Z",
"CONTROL":"N",
"PKEY":"UD0000000000720",
"Name":"rajat10 10:19",
"Tenor":"0Y",
"Size":0,
"Price_Guidance":"43%",
"Remarks":"-",
"Book_Size":20,
"Status":"Open",
"No_Of_Orders":2,
"Current_Cut_Off":2.3,
"Book":"Book#ReOffer",
"Save":"Edit"
},
{
"ORDCOLUMN":"2017-11-17T05:00:00.000000000Z",
"CONTROL":"Y",
"PKEY":"UD0000000000720",
"Name":"rajat10 10:19",
"Tenor":"Multi ...",
"Size":0,
"Price_Guidance":"-",
"Remarks":"-",
"Book_Size":20,
"Status":" Open",
"No_Of_Orders":2,
"Current_Cut_Off":2.3,
"Book":"Book#ReOffer",
"Save":"Edit"
},
{
"ORDCOLUMN":"2017-11-17T05:00:00.000000000Z",
"CONTROL":"N",
"PKEY":"UD0000000000720",
"Name":"rajat10 10:19",
"Tenor":"Perp",
"Size":0,
"Price_Guidance":"19%",
"Remarks":"-",
"Book_Size":0,
"Status":"Open",
"No_Of_Orders":2,
"Current_Cut_Off":2.3,
"Book":"Book#ReOffer",
"Save":"Edit"
}
....and so on
]
So, this data can be grouped by PKEY and parent object has control - "Y", child object has control - "N". Note:- There can be objects where there is only parent deal with no child deals.
In my app.js:-
$scope.parentDeals = $scope.allDeals.filter(function (item,index) {
return item.CONTROL == "Y";
});
$scope.childDeals = [];
$scope.childShow = function (PKEY) {
if($scope["childRowShow_"+PKEY]){
$scope["childRowShow_"+PKEY] = false;
}
else{
$scope.childDeals = $scope.allDeals.filter(function (item,index) {
if(item.PKEY == PKEY && item.CONTROL == "N"){
return item;
}
});
$scope["childRowShow_"+PKEY] = true;
}
};
Here, I am making two arrays:- parentDeals and childDeals.
Right now, I am applying ng-repeat on the separate row so, child deals are showing after all parent deals. Is there any way I can show them below the respective parent deals or can apply a different solution?
Yes, with ng-repeat-start and ng-repeat-end, we can explicitly specify the starting and ending for ng-repeat. So, instead of using the ng-repeat directive on one single DOM element, we can specify the ng-repeat-start and ng-repeat-end on any two DOM elements.
For eg.
<div ng-app="app">
<table ng-controller="TestController">
<tr ng-repeat-start="d in data">
<td><strong>{{d.name}}</strong></td>
</tr>
<tr ng-repeat-end>
<td>{{ d.info }}</td>
</tr>
</table>
</div>
<script>
var app = angular.module('app', []);
app.controller('TestController', function ($scope) {
$scope.data = [{
name: 'ABC',
info: 'Bangalore'
}, {
name: 'XYZ',
info: 'Mumbai'
}];
});
</script>

angular angular-table dynamic header name

I use angular and angular-table to display multiple tables on the same page.
I need to create dynamic table with dynamic header and dynamic content.
Plunkr her
This is a working example with non dynamic header but I don't find how to make dynamic
The controller :
angular.module('plunker', ['ui.bootstrap',"angular-table","angular-tabs"]);
function ListCtrl($scope, $dialog) {
$scope.cols= ['index','name','email'];
$scope.list = [
{ index: 1, name: "Kristin Hill", email: "kristin#hill.com" },
{ index: 2, name: "Valerie Francis", email: "valerie#francis.com" },
...
];
$scope.config = {
itemsPerPage: 5,
fillLastPage: true
};
}
HTML
<!-- this work -->
<table class="table table-striped" at-table at-paginated at-list="list" at-config="config">
<thead></thead>
<tbody>
<tr>
<td at-implicit at-sortable at-attribute="name"></td>
<td at-implicit at-sortable at-attribute="name"></td>
<td at-implicit at-sortable at-attribute="email"></td>
</tr>
</tbody>
</table>
<!-- this fail ... -->
<table class="table table-striped" at-table at-paginated at-list="list" at-config="config">
<thead></thead>
<tbody>
<tr>
<td ng-repeat='col in cols' at-implicit at-sortable at-attribute="{{col}}"></td>
</tr>
</tbody>
</table>
I am missing some think or it is not possible with this module ?
Did you know another module where you can have dynamic header and pagination ? ( i try also ngTable but have some bug issu with data not being displayed )
Through the below code, you can generate dynamic header
<table class="table table-hover table-striped">
<tbody>
<tr class="accordion-toggle tblHeader">
<th ng-repeat="(key, val) in columns">{{key}}</th>
</tr>
<tr ng-repeat="row in rows">
<td ng-if="!$last" ng-repeat="col in key(row)" ng-init="val=row[col]">
{{val}}
</td>
</tr>
</tbody>
</table>
Angular Script
var app = angular.module('myApp', []);
app.controller('myControl', function ($scope, $http) {
$http.get('http://jsonplaceholder.typicode.com/todos').success(function (data) {
$scope.columns = data[0];
$scope.rows = data;
}).error(function (data, status) {
});
$scope.key = function (obj) {
if (!obj) return [];
return Object.keys(obj);
}
});

How to use ng-repeat for array in array using single ng-repeat

I got a json of table which has columns and rows as below
$scope.table = {
Columns: [{Header:"22-Jul-15",SubHeaders: ["10:33 AM"]}
, {Header:"21-Jul-15",SubHeaders: ["03:40 AM"]}
, {Header:"17-Jul-15",SubHeaders: ["01:05 PM", "12:06 PM"]}]
, Rows:[{Items:[{Value:1},{Value:5},{Value:8},{Value:""}]}
,{Items:[{Value:2},{Value:6},{Value:9},{Value:""}]}
,{Items:[{Value:3},{Value:7},{Value:10},{Value:15}]}]
} //end of table
I want to display Columns.SubHeaders as Sub header row of a table.
Here what I tried, but did not work
<table class="table table-stripped table-bordered">
<thead>
<tr>
<th ng-repeat="col in table.Columns" colspan="{{col.SubHeaders.length}}">{{col.Header}}</th>
</tr>
<tr>
<td class="center text-black" ng-repeat="head in table.Columns[0].SubHeaders">{{head}}</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in table.Rows">
<td ng-repeat="item in row.Items">
{{item.Value}}
</td>
</tr>
</tbody>
</table>
I used head in table.Columns[0].SubHeaders just to show it is working for hard-coded index value.
How can I achieve this using single ng-repeat? I can use two ng-repeats but it will lead to unnecessary html markup.
Here is the complete fiddle
I created this fiddler (forked from yours):
https://jsfiddle.net/b50hvzef/1/
The idea is to join the subheaders as they are they actual columns:
<td class="center text-black" ng-repeat="head in subHeaders">{{head}}</td>
and the code looks like this:
var app = angular.module("app",[]);
app.controller("MyController", function ($scope, $http) {
$scope.table = {
Columns: [{Header:"22-Jul-15",SubHeaders: ["10:33 AM"]}
, {Header:"21-Jul-15",SubHeaders: ["03:40 AM"]}
, {Header:"17-Jul-15",SubHeaders: ["01:05 PM", "12:06 PM"]}]
,Rows:[{Items:[{Value:1},{Value:5},{Value:8}]}
,{Items:[{Value:2},{Value:6},{Value:9}]}
,{Items:[{Value:3},{Value:7},{Value:10}]}]
};
var subHeaders = [];
$scope.table.Columns.forEach(function(col) {
col.SubHeaders.forEach(function(subHeader) {
subHeaders.push(subHeader);
});
});
$scope.subHeaders = subHeaders;
});
Note that there is still a mismatch between columns and data. But it's up to you how to solve it.
Hope this helps.

Get ng-repeat to use object property order

I have a dynamic dataset to present with Angular. In other words I do not have access to the column names returned until runtime.
I can present the column names as a header and the data itself with no problem. ng-repeat (or perhaps it's JS itself) though refuses to return the columns in the order they were created. You can see in the fiddle the columns are sorted so they appear "age name weight", I need them the way they came, "name age weight"
I created another array of the column names and their proper order ($scope.order) but I cannot seem to find a way to use that with Angular to sort the data.
Please give me a way to present this data in the original order.
I created a JSFiddle: http://jsfiddle.net/GE7SW/
Here's a simple scope that sets up the data:
function MainCtrl($scope) {
$scope.output = [
{
"name": "Tom",
"age": "25",
"weight" : 250
},
{
"name": "Allan",
"age": "28",
"weight" : 175
},
{
"name": "Sally",
"age": "35",
"weight" : 150
}
];
$scope.order = {
"name": 1,
"age": 2,
"weight" : 3
};
}
Here's the HTML:
<table ng-app ng-controller="MainCtrl">
<thead>
<tr>
<th ng-repeat="(key,value) in output.0">{{key}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in output">
<td ng-repeat="(key,value) in row">{{value}}</td>
</tr>
</tbody>
</table>
(Note the (key,value) in the last ng-repeat is needed by ng-class code I took out for this example.)
The properties order in JavaScript objects is never guaranteed. You need to use a list.
The only thing you need to do is convert $scope.order into an array:
$scope.order = [
"name",
"age",
"weight"
];
and use that inside the HTML like this:
<table ng-app ng-controller="MainCtrl">
<thead>
<tr>
<th ng-repeat="key in order">{{key}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in output">
<td ng-repeat="key in order">{{row[key]}}</td>
</tr>
</tbody>
</table>
Fiddle
Your updated fiddle here (click).
While the order of javascript objects is not guaranteed, this is likely to work in most or all cases. This is simply looping your objects into arrays. It might be a better approach, if possible, to have the data coming from the server in arrays, 1 that describes the structure (keys) and the other that just data sets of arrays.
$scope.getRow = function(row) {
var arr = [];
for (var k in row) {
if (k !== '$$hashKey') {
arr.push(row[k]);
}
}
return arr;
};
$scope.getKeys = function(row) {
var arr = [];
for (var k in row) {
if (k !== '$$hashKey') {
arr.push(k);
}
}
return arr;
};
the html:
<table ng-app ng-controller="MainCtrl">
<thead>
<tr>
<th ng-repeat="(key,value) in getKeys(output[0])">{{value}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in output">
<td ng-repeat="(key, value) in getRow(row)" ng-class="getKeys(output[0])[key]">{{value}}</td>
</tr>
</tbody>
</table>

Resources