Created
March 28, 2013 04:07
-
-
Save kirkbushell/5260524 to your computer and use it in GitHub Desktop.
Paginator module for AngularJS, in combination with Laravel's paginator class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Paginator | |
* | |
* The paginator can be used within any controller to easily set up | |
* some pagination options, including number of pages, page navigation | |
* and more. It is built to work with Laravel's own pagination library, | |
* which returns data in a particular format. | |
* | |
* Usage: | |
* Before you can use paginator, make sure you specify the URLs to your pagination | |
* templates, like so. In this example, I will assume that App is your angular application instance: | |
* | |
* App.value('paginator.config', { | |
* templates: { | |
* info: '/partials/pagination/info.html', | |
* pagination: '/partials/pagination/pagination.html' | |
* } | |
* }); | |
* | |
* Example: | |
* Inside your controller, add the following. The first argument is your scope variable. | |
* Second argument is the name of the service/module you'll be using to fetch the data. Third | |
* is the name of the $scope.params.property that you want to store the data on, and 4th is the callback | |
* method, if needed, for doing data transformations. | |
* | |
* Paginate($scope, Category, 'categories'); | |
* | |
* @param object $scope | |
* @param object Service - The Service to use. This could be the actual service (Such as User, in which | |
* case Paginator will assume the method "get"), or a custom method for the service, | |
* such as User.retrieve. | |
* @param string records - Name of the records variable to set the data to on $scope | |
* @param function callback - For when the paginator makes queries, | |
* can allow the developer to customize the data's format | |
* @author Kirk Bushell | |
* @date 9th January 2013 | |
*/ | |
var module = angular.module('core.paginator', []); | |
module.factory('Paginate', [function() { | |
return function($scope, Service, records, callback) { | |
if (!$scope.params) $scope.params = {}; | |
// Defaults | |
$scope.currentPage = 0; | |
$scope.params.per_page = 10; | |
$scope.params.order = null; | |
var fieldOrder = 'asc'; | |
function setPagination(data) { | |
$scope[records] = data; | |
$scope.params.per_page = $scope[records].per_page; | |
$scope.total = $scope[records].total; | |
$scope.totalPages = $scope[records].last; | |
$scope.pages = []; | |
for(var i=1; i<=$scope.totalPages;i++) { | |
$scope.pages.push(i); | |
} | |
$scope.nextPage = function() { | |
if($scope.currentPage < $scope.totalPages) { | |
$scope.currentPage++; | |
} | |
} | |
$scope.prevPage = function() { | |
if($scope.currentPage > 1) { | |
$scope.currentPage--; | |
} | |
} | |
$scope.firstPage = function() { | |
$scope.currentPage = 1; | |
} | |
$scope.lastPage = function() { | |
$scope.currentPage = $scope.totalPages; | |
} | |
$scope.setPage = function(page) { | |
$scope.currentPage = page; | |
$scope.params.page = page; | |
} | |
if (callback) callback($scope); | |
// Trigger an event that the pagination has been updated. | |
$scope.$broadcast('pagination.updated'); | |
} | |
/** | |
* Trigger to update the pagination and the table data. | |
* | |
* The only optional param is which page to update to. If nothing | |
* is passed, it will return to page 1. | |
*/ | |
$scope.$on('pagination.update', function( e , newPage ) { | |
if ( !newPage ) newPage = 1; | |
$scope.params.page = newPage; | |
for ( var i in $scope.params ) { | |
if ( $scope.params[i] == null || $scope.params[i] == 'null' ) { | |
delete $scope.params[i]; | |
} | |
} | |
var caller = Service.get; | |
caller($scope.params, function(data) { | |
setPagination(data); | |
}); | |
}) | |
/** | |
* Trigger to reload data based on filters. | |
* | |
* If we're on the first page, we trigger the update function, but if | |
* we're on any other page, all we need to do is update the variable | |
* and that will automatically trigger the update. | |
*/ | |
$scope.filter = function() { | |
if ( $scope.currentPage == 1 ) { | |
$scope.$broadcast('pagination.update', [ 1 ]); | |
} | |
else { | |
$scope.currentPage = 1; | |
} | |
}; | |
/** | |
* Sets the ordering for the data to be retrieved from the server | |
*/ | |
$scope.order = function(field) { | |
if ($scope.params.order == field) { | |
fieldOrder = fieldOrder == 'asc' ? 'desc' : 'asc'; | |
} | |
$scope.params.direction = fieldOrder; | |
$scope.params.order = field; | |
// Trigger an update for the pagination. | |
$scope.$broadcast('pagination.update', [ 1 ]); | |
}; | |
// Watch the currentPage variable and update the pagination whenever it changes. | |
$scope.$watch('currentPage', function( newPage , oldPage ) { | |
$scope.$broadcast('pagination.update', [ newPage ]); | |
}); | |
// Execute first call | |
$scope.currentPage = 1; | |
} | |
}]); | |
/** | |
* Used for rendering the actual pagination. | |
*/ | |
module.directive('pagination', ['paginator.config', function(config) { | |
return { | |
templateUrl: viewPath(config.templates.pagination) | |
}; | |
}]); | |
/** | |
* Used for rendering the actual pagination. | |
*/ | |
module.directive('paginationInfo', ['paginator.config', function(config) { | |
return { | |
templateUrl: viewPath(config.templates.info), | |
link: function(scope, iElement, iAttrs) { | |
scope.min = 0; | |
scope.max = 0; | |
// Listen to the event 'pagination.updated' and update the pagination | |
// info directive. | |
scope.$on('pagination.updated', function( e ) { | |
// Calculate the min/max by comparing the params.page variable, instead of the | |
// currentPage. The params.page variable is ALWAYS updated whereas currentPage will | |
// not be updated in cases where all items are deleted from page 2. | |
scope.min = scope.params.page * scope.params.per_page - scope.params.per_page + 1; | |
scope.max = scope.params.page * scope.params.per_page; | |
// Obviously if max is greater than total, we have very few records | |
// or we're at the end of the pagination. | |
if (scope.max > scope.total) scope.max = scope.total; | |
}); | |
} | |
}; | |
}]); | |
/** | |
* Used for setting sort options for a field | |
*/ | |
module.directive('paginateSort', ['paginator.config', function(config) { | |
return { | |
link: function(scope, element, attrs) { | |
var field = attrs.paginateSort; | |
// Add the class 'sortable' to give a default styling. | |
element.addClass('sortable'); | |
element.on('click', function() { | |
scope.order(field); | |
element.removeClass('sort-asc sort-desc').addClass( 'sort-' + scope.params.direction ); | |
}); | |
scope.$watch('params.order', function(newValue, oldValue) { | |
if (newValue && newValue != field) | |
element.removeClass('sort-asc sort-desc'); | |
}); | |
} | |
}; | |
}]); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment