ng2-pagination
Version:
Pagination for Angular
122 lines (121 loc) • 4.98 kB
JavaScript
;
var core_1 = require("@angular/core");
var pagination_service_1 = require("./pagination.service");
var LARGE_NUMBER = Number.MAX_SAFE_INTEGER;
var PaginatePipe = (function () {
function PaginatePipe(service) {
this.service = service;
// store the values from the last time the pipe was invoked
this.state = {};
}
PaginatePipe.prototype.transform = function (collection, args) {
// When an observable is passed through the AsyncPipe, it will output
// `null` until the subscription resolves. In this case, we want to
// use the cached data from the `state` object to prevent the NgFor
// from flashing empty until the real values arrive.
if (args instanceof Array) {
// compatible with angular2 before beta16
args = args[0];
}
if (!(collection instanceof Array)) {
var _id = args.id || this.service.defaultId;
if (this.state[_id]) {
return this.state[_id].slice;
}
else {
return collection;
}
}
var serverSideMode = args.totalItems && args.totalItems !== collection.length;
var instance = this.createInstance(collection, args);
var id = instance.id;
var start, end;
var perPage = instance.itemsPerPage;
this.service.register(instance);
if (!serverSideMode && collection instanceof Array) {
perPage = +perPage || LARGE_NUMBER;
start = (instance.currentPage - 1) * perPage;
end = start + perPage;
var isIdentical = this.stateIsIdentical(id, collection, start, end);
if (isIdentical) {
return this.state[id].slice;
}
else {
var slice = collection.slice(start, end);
this.saveState(id, collection, slice, start, end);
this.service.change.emit(id);
return slice;
}
}
// save the state for server-side collection to avoid null
// flash as new data loads.
this.saveState(id, collection, collection, start, end);
return collection;
};
/**
* Create an PaginationInstance object, using defaults for any optional properties not supplied.
*/
PaginatePipe.prototype.createInstance = function (collection, args) {
var config = args;
this.checkConfig(config);
return {
id: config.id || this.service.defaultId(),
itemsPerPage: config.itemsPerPage || 0,
currentPage: config.currentPage || 1,
totalItems: config.totalItems || collection.length
};
};
/**
* Ensure the argument passed to the filter contains the required properties.
*/
PaginatePipe.prototype.checkConfig = function (config) {
var required = ['itemsPerPage', 'currentPage'];
var missing = required.filter(function (prop) { return !(prop in config); });
if (0 < missing.length) {
throw new Error("PaginatePipe: Argument is missing the following required properties: " + missing.join(', '));
}
};
/**
* To avoid returning a brand new array each time the pipe is run, we store the state of the sliced
* array for a given id. This means that the next time the pipe is run on this collection & id, we just
* need to check that the collection, start and end points are all identical, and if so, return the
* last sliced array.
*/
PaginatePipe.prototype.saveState = function (id, collection, slice, start, end) {
this.state[id] = {
collection: collection,
size: collection.length,
slice: slice,
start: start,
end: end
};
};
/**
* For a given id, returns true if the collection, size, start and end values are identical.
*/
PaginatePipe.prototype.stateIsIdentical = function (id, collection, start, end) {
var state = this.state[id];
if (!state) {
return false;
}
var isMetaDataIdentical = state.size === collection.length &&
state.start === start &&
state.end === end;
if (!isMetaDataIdentical) {
return false;
}
return state.slice.every(function (element, index) { return element === collection[start + index]; });
};
PaginatePipe.decorators = [
{ type: core_1.Pipe, args: [{
name: 'paginate',
pure: false
},] },
];
/** @nocollapse */
PaginatePipe.ctorParameters = function () { return [
{ type: pagination_service_1.PaginationService, },
]; };
return PaginatePipe;
}());
exports.PaginatePipe = PaginatePipe;