Hi everyone,
I recently started learning AngularJS and created a basic item list with search functionality and pagination. Everything was working smoothly, so I decided to move my list outside the controller and store it as a JSON file.
Here's what I did:
HTML
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Test angular</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="text/javascript" src="js/angular.min.js"></script>
<script type="text/javascript" src="js/controllers.js"></script>
<!-- Place favicon.ico and apple-touch-icon.png in the root directory -->
</head>
<body >
<section class="app" ng-app="myApp" data-scope="$scope = myApp" >
<div ng-controller="myCtrl" data-scope="$scope = myApp.myCtrl">
<input type="text" ng-model="search" data-scope="$scope = myApp.myCtrl.items(repeater scope)">
Search = {{ search }}
<div class="item" ng-repeat="item in newItems | filter:search | startFrom:currentPage*pageSize | limitTo:pageSize">
{{ item.name }}
</div>
<button ng-disabled="currentPage == 0" ng-click="currentPage=currentPage-1">
Previous
</button>
{{currentPage+1}}/{{numberOfPages()}}
<button ng-disabled="currentPage >= items.length/pageSize - 1" ng-click="currentPage=currentPage+1">
Next
</button>
</div>
</section>
</body>
</html>
Note: The data-scope attributes are used for scope visibility.
controllers.js
var myApp = angular.module('myApp', []);
myApp.filter('startFrom', function() {
return function(input, start) {
start = +start;
return input.slice(start);
}
});
myApp.controller('myCtrl', function($scope, $interval, $filter, $http){
$scope.currentPage = 0;
$scope.pageSize = 10;
$scope.numberOfPages=function(){
return Math.ceil($scope.items.length/$scope.pageSize);
}
$scope.$watch('search', function () {
$scope.currentPage = 0;
$scope.newItems = $filter('filter')($scope.items, $scope.search);
$scope.numberOfPages=function(){
return Math.ceil($scope.items.length/$scope.pageSize);
}
});
$scope.newItems = $scope.items;
$http.get('js/items.json')
.then(function(res){
$scope.items = res.data;
});
});
The JSON loads successfully, but there seems to be an error regarding the use of the startFrom
filter:
TypeError: Cannot call method 'slice' of undefined
My assumption is that the filter is trying to slice something that isn't defined yet, possibly due to the ordering of operations.
UPDATE :
After initializing $scope.items = []; as suggested by VtoCorleone, the previous errors were resolved. However, a new issue emerged where the first page of the list doesn't display any items, although pagination works as expected.
My proposed solution involves setting two properties for items (items
, newItems
). items
contains the original JSON data, while newItems
stores filtered results. By using items
, all items can be retained and restored if necessary.
Upon inspecting with Angular inspector, on page load, items
is populated with the JSON data, whereas newItems
remains empty. This leads to the items not displaying properly despite being available in the JSON. Why is this happening?