Reputation: 4704
I am displaying a JSON in a Bootstrap 3 table, in AngularJS.
I am working on paginating the table, with the help of the limitTo
filter:
var root = 'https://jsonplaceholder.typicode.com';
// Create an Angular module named "usersApp"
var app = angular.module("usersApp", []);
// Create controller for the "usersApp" module
app.controller("usersCtrl", ["$scope", "$http", function($scope, $http) {
var url = root + "/users"
$http.get(url)
.then(function(data) {
// Users arary
$scope.users = data.data;
// Order by function
$scope.orderByMe = function(criteria) {
$scope.myOrderBy = criteria;
}
// Paginate
$scope.pageNum = 1;
$scope.perPage = 5;
$scope.startAt = 0;
$scope.prevPage = function() {
if ($scope.pageNum > 1) {
$scope.pageNum = $scope.pageNum - 1;
$scope.startAt = ($scope.pageNum - 1) * $scope.perPage;
}
};
$scope.nextPage = function() {
$scope.pageNum = $scope.pageNum + 1;
$scope.startAt = ($scope.pageNum - 1) * $scope.perPage;
};
});
}]);
body {
padding-top: 70px;
}
.container {
padding: 0 10px;
}
.search-box {
margin: 5px;
}
.panel-heading {
font-weight: bold;
}
.table-container {
margin: 10px 0;
}
.table-container .panel-body {
padding: 0;
}
.table-container table {
margin-bottom: 0;
border-width: 0;
border-top-width: 1px;
border-bottom-width: 1px;
}
.table-container table tr:last-child td {
border-bottom: none;
}
.table-container table tr th {
font-weight: bold;
cursor: pointer;
}
.table-container table tr th:first-child {
border-left: none;
}
.table-container table tr td:first-child {
border-left: none;
}
.table-container table tr th:last-child, .table-container table tr td:last-child {
border-right: none;
}
/* Media queries */
@media (min-width: 768px) {
.container {
width: auto;
}
}
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">My App</a>
</div>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Home</a></li>
<li class="active"><a href="#">Users</a></li>
<li><a href="#">Posts</a></li>
</ul>
</div>
</nav>
<div class="container" data-ng-app="usersApp">
<div class="panel panel-default table-container">
<div class="panel-heading">Users</div>
<div class="panel-body" data-ng-controller="usersCtrl">
<div class="row">
<div class="col-sm-12">
<div class="form-group search-box">
<input type="text" class="form-control" id="search" placeholder="Search User" data-ng-model="search">
</div>
</div>
<div class="col-sm-12">
<div class="table-responsive">
<table class="table table-striped table-bordered" id="dataTable">
<thead>
<tr>
<th ng-click="orderByMe('name')">Full name</th>
<th ng-click="orderByMe('email')">Email</th>
<th ng-click="orderByMe('city')">City</th>
<th>Street</th>
<th>Suite</th>
<th>Zipcode</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="user in users|filter:search|orderBy:myOrderBy| limitTo : perPage : startAt">
<td>{{user.name}}</td>
<td><a href="mailto:{{user.email | lowercase}}">{{user.email | lowercase}}</a></td>
<td>{{user.address.city}}</td>
<td>{{user.address.street}}</td>
<td>{{user.address.suite}}</td>
<td>{{user.address.zipcode}}</td>
</tr>
</tbody>
</table>
</div>
<p class="text-center">Page {{pageNum}}</p>
<p class="text-center">Show users from {{startAt + 1}} to {{startAt + perPage}}</p>
<div class="text-center">
<ul class="pager">
<li><a href="#" ng-click="prevPage()">← Previous</a></li>
<li><a href="#" ng-click="nextPage()">Next →</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
Upon clicking the Next and Prev buttons, the startAt
parameter of the limitTo
does update in the view, as can be seen in the paragraph below the table, but the data-ng-repeat
does not (re)use it updated.
How do I render the table at every update of startAt
?
What is missing from my script?
Upvotes: 0
Views: 516
Reputation: 4704
Here is a better (and nicer) version:
var root = 'https://jsonplaceholder.typicode.com';
// Create an Angular module named "usersApp"
var app = angular.module("usersApp", []);
// Create controller for the "usersApp" module
app.controller("usersCtrl", ["$scope", "$http", function($scope, $http) {
var url = root + "/users"
$http.get(url)
.then(function(data) {
// Users arary
$scope.users = data.data;
// Order by function
$scope.orderByMe = function(criteria) {
$scope.myOrderBy = criteria;
}
// Paginate
$scope.pageNum = 1;
$scope.perPage = 3;
$scope.startAt = 0;
$scope.itemsCount = $scope.users.length;
$scope.pageMax = Math.ceil($scope.itemsCount / $scope.perPage);
$scope.prevPage = function() {
if ($scope.pageNum > 1) {
$scope.pageNum = $scope.pageNum - 1;
$scope.startAt = ($scope.pageNum - 1) * $scope.perPage;
}
};
$scope.nextPage = function() {
if ($scope.pageNum < $scope.pageMax) {
$scope.pageNum = $scope.pageNum + 1;
$scope.startAt = ($scope.pageNum - 1) * $scope.perPage;
}
};
});
}]);
body {
padding-top: 70px;
}
.container {
padding: 0 10px;
}
.search-box {
margin: 5px !important;
}
.panel-heading {
font-weight: bold;
}
.table-container {
margin: 10px 0;
}
.table-container .panel-body {
padding: 0;
}
.table-container table {
margin-bottom: 0;
border-width: 0;
border-top-width: 1px;
border-bottom-width: 1px;
}
.table-container table tr:last-child td {
border-bottom: none;
}
.table-container table tr th {
font-weight: bold;
cursor: pointer;
}
.table-container table tr th:first-child {
border-left: none;
}
.table-container table tr td:first-child {
border-left: none;
}
.table-container table tr th:last-child, .table-container table tr td:last-child {
border-right: none;
}
.table-container .pagination-info {
margin: 10px 0;
}
.pager {
margin: 10px 0;
}
/* Media queries */
@media (min-width: 768px) {
.container {
width: auto;
}
}
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">My App</a>
</div>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Home</a></li>
<li class="active"><a href="#">Users</a></li>
<li><a href="#">Posts</a></li>
</ul>
</div>
</nav>
<div class="container" data-ng-app="usersApp">
<div class="panel panel-default table-container">
<div class="panel-heading">Users</div>
<div class="panel-body" data-ng-controller="usersCtrl">
<div class="row">
<div class="col-sm-12">
<div class="form-group search-box">
<input type="text" class="form-control" id="search" placeholder="Search User" data-ng-model="search">
</div>
</div>
<div class="col-sm-12">
<div class="table-responsive">
<table class="table table-striped table-bordered" id="dataTable">
<thead>
<tr>
<th>#</th>
<th ng-click="orderByMe('name')">Full name</th>
<th ng-click="orderByMe('email')">Email</th>
<th ng-click="orderByMe('city')">City</th>
<th>Street</th>
<th>Suite</th>
<th>Zipcode</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="user in users|filter:search|orderBy:myOrderBy| limitTo : perPage : startAt">
<td>{{$index + startAt + 1}}</td>
<td>{{user.name}}</td>
<td><a href="mailto:{{user.email | lowercase}}">{{user.email | lowercase}}</a></td>
<td>{{user.address.city}}</td>
<td>{{user.address.street}}</td>
<td>{{user.address.suite}}</td>
<td>{{user.address.zipcode}}</td>
</tr>
</tbody>
</table>
</div>
<p class="pagination-info text-center">Page {{pageNum}} of {{pageMax}}</p>
<div class="text-center" ng-if="pageMax > 1">
<ul class="pager">
<li><a href="#" ng-click="prevPage()">← Previous</a></li>
<li><a href="#" ng-click="nextPage()">Next →</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
Upvotes: 0
Reputation: 4704
Using a "modern" version of AngularJS did the job:
var root = 'https://jsonplaceholder.typicode.com';
// Create an Angular module named "usersApp"
var app = angular.module("usersApp", []);
// Create controller for the "usersApp" module
app.controller("usersCtrl", ["$scope", "$http", function($scope, $http) {
var url = root + "/users"
$http.get(url)
.then(function(data) {
// Users arary
$scope.users = data.data;
// Order by function
$scope.orderByMe = function(criteria) {
$scope.myOrderBy = criteria;
}
// Paginate
$scope.pageNum = 1;
$scope.perPage = 5;
$scope.startAt = 0;
$scope.usersCount= $scope.users.length;
$scope.pageMax = Math.ceil($scope.usersCount/$scope.perPage);
$scope.prevPage = function() {
if ($scope.pageNum > 1) {
$scope.pageNum = $scope.pageNum - 1;
$scope.startAt = ($scope.pageNum - 1) * $scope.perPage;
}
};
$scope.nextPage = function() {
if ($scope.pageNum < $scope.pageMax) {
$scope.pageNum = $scope.pageNum + 1;
$scope.startAt = ($scope.pageNum - 1) * $scope.perPage;
}
};
});
}]);
body {
padding-top: 70px;
}
.container {
padding: 0 10px;
}
.search-box {
margin: 5px !important;
}
.panel-heading {
font-weight: bold;
}
.table-container {
margin: 10px 0;
}
.table-container .panel-body {
padding: 0;
}
.table-container .table-responsive {
margin: 0 0 10px 0;
}
.table-container table {
border-width: 0;
border-top-width: 1px;
border-bottom-width: 1px;
margin-bottom: 0;
}
.table-container p {
margin-bottom: 0;
}
.table-container .pager {
margin: 5px 0 10px 0;
}
.table-container table tr:last-child td {
border-bottom: none;
}
.table-container table tr th {
font-weight: bold;
cursor: pointer;
}
.table-container table tr th:first-child {
border-left: none;
}
.table-container table tr td:first-child {
border-left: none;
}
.table-container table tr th:last-child, .table-container table tr td:last-child {
border-right: none;
}
/* Media queries */
@media (min-width: 768px) {
.container {
width: auto;
}
}
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">My App</a>
</div>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Home</a></li>
<li class="active"><a href="#">Users</a></li>
<li><a href="#">Posts</a></li>
</ul>
</div>
</nav>
<div class="container" data-ng-app="usersApp">
<div class="panel panel-default table-container">
<div class="panel-heading">Users</div>
<div class="panel-body" data-ng-controller="usersCtrl">
<div class="row">
<div class="col-sm-12">
<div class="form-group search-box">
<input type="text" class="form-control" id="search" placeholder="Search User" data-ng-model="search">
</div>
</div>
<div class="col-sm-12">
<div class="table-responsive">
<table class="table table-striped table-bordered" id="dataTable">
<thead>
<tr>
<th ng-click="orderByMe('name')">Full name</th>
<th ng-click="orderByMe('email')">Email</th>
<th ng-click="orderByMe('city')">City</th>
<th>Street</th>
<th>Suite</th>
<th>Zipcode</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="user in users|filter:search|orderBy:myOrderBy| limitTo : perPage : startAt">
<td>{{user.name}}</td>
<td><a href="mailto:{{user.email | lowercase}}">{{user.email | lowercase}}</a></td>
<td>{{user.address.city}}</td>
<td>{{user.address.street}}</td>
<td>{{user.address.suite}}</td>
<td>{{user.address.zipcode}}</td>
</tr>
</tbody>
</table>
</div>
<p class="text-center">Show users {{startAt + 1}} to {{startAt + perPage}} of {{usersCount}} users </p>
<div class="text-center">
<ul class="pager">
<li><a href="#" ng-click="prevPage()">← Previous</a></li>
<li><a href="#" ng-click="nextPage()">Next →</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
Upvotes: 1
Reputation: 521
1.2.23 doesn't have begin in limitTo, lowest version I found that supports begin is 1.4.0
Here is a working plunk. https://plnkr.co/edit/bcrlKW46zlZ20k6E57M4
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
Upvotes: 1