Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

ng2-pagination

Package Overview
Dependencies
Maintainers
1
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ng2-pagination - npm Package Compare versions

Comparing version 0.0.1-alpha.13 to 0.0.1-beta.1

dist/template.d.ts

2

dist/ng2-pagination.d.ts
export { PaginatePipe } from './paginate-pipe';
export { PaginationService, IPaginationInstance } from './pagination-service';
export { PaginationControlsCmp } from './pagination-controls-cmp';
export { PAGINATION_DIRECTIVES } from './pagination-controls-cmp';

@@ -6,2 +6,2 @@ var paginate_pipe_1 = require('./paginate-pipe');

var pagination_controls_cmp_1 = require('./pagination-controls-cmp');
exports.PaginationControlsCmp = pagination_controls_cmp_1.PaginationControlsCmp;
exports.PAGINATION_DIRECTIVES = pagination_controls_cmp_1.PAGINATION_DIRECTIVES;

@@ -7,4 +7,11 @@ import { PaginationService } from "./pagination-service";

transform(collection: any[], args: any[]): any;
/**
* Create an IPaginationInstance object, using defaults for any optional properties not supplied.
*/
private createInstance(collection, args);
/**
* Ensure the argument passed to the filter contains the required properties.
*/
private checkConfig(config);
/**
* To avoid returning a brand new array each time the pipe is run, we store the state of the sliced

@@ -17,5 +24,5 @@ * array for a given id. This means that the next time the pipe is run on this collection & id, we just

/**
* For a given id, returns true if the collection, start and end values are identical.
* For a given id, returns true if the collection, size, start and end values are identical.
*/
private stateIsIdentical(id, collection, start, end);
}

@@ -20,20 +20,25 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {

PaginatePipe.prototype.transform = function (collection, args) {
// for non-array types, throw an exception
// 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 (!(collection instanceof Array)) {
throw new Error("PaginationPipe: Argument error - expected an array, got " + typeof collection);
var _id = args[0].id || this.service.defaultId;
if (this.state[_id]) {
return this.state[_id].slice;
}
else {
return collection;
}
}
var usingConfig = typeof args[0] === 'object';
var serverSideMode = usingConfig && args[0].totalItems !== undefined;
var serverSideMode = args[0].totalItems !== undefined;
var instance = this.createInstance(collection, args);
var id = instance.id;
var start, end;
var perPage = instance.itemsPerPage;
this.service.register(instance);
if (!usingConfig && instance.totalItems !== collection.length) {
this.service.setTotalItems(id, collection.length);
}
var itemsPerPage = instance.itemsPerPage;
if (!serverSideMode && collection instanceof Array) {
itemsPerPage = itemsPerPage || LARGE_NUMBER;
start = (this.service.getCurrentPage(id) - 1) * itemsPerPage;
end = start + itemsPerPage;
perPage = perPage || LARGE_NUMBER;
start = (instance.currentPage - 1) * perPage;
end = start + perPage;
var isIdentical = this.stateIsIdentical(id, collection, start, end);

@@ -46,30 +51,33 @@ if (isIdentical) {

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 IPaginationInstance object, using defaults for any optional properties not supplied.
*/
PaginatePipe.prototype.createInstance = function (collection, args) {
var instance;
if (typeof args[0] === 'string' || typeof args[0] === 'number') {
var id = this.service.defaultId;
instance = {
id: id,
itemsPerPage: parseInt(args[0]),
currentPage: this.service.getCurrentPage(id) || 1,
totalItems: collection.length
};
var config = args[0];
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 !config.hasOwnProperty(prop); });
if (0 < missing.length) {
throw new Error("PaginatePipe: Argument is missing the following required properties: " + missing.join(', '));
}
else if (typeof args[0] === 'object') {
instance = {
id: args[0].id || this.service.defaultId,
itemsPerPage: args[0].itemsPerPage || 0,
currentPage: args[0].currentPage,
totalItems: args[0].totalItems || collection.length
};
}
else {
throw new Error("PaginatePipe: Argument must be a string, number or an object. Got " + typeof args[0]);
}
return instance;
};

@@ -85,2 +93,3 @@ /**

collection: collection,
size: collection.length,
slice: slice,

@@ -92,3 +101,3 @@ start: start,

/**
* For a given id, returns true if the collection, start and end values are identical.
* For a given id, returns true if the collection, size, start and end values are identical.
*/

@@ -100,3 +109,7 @@ PaginatePipe.prototype.stateIsIdentical = function (id, collection, start, end) {

}
return state.collection === collection && state.start === start && state.end === end;
return state.collection === collection &&
state.size === collection.length &&
state.start === start &&
state.end === end;
state.end === end;
};

@@ -103,0 +116,0 @@ PaginatePipe = __decorate([

@@ -1,2 +0,2 @@

import { EventEmitter, ViewContainerRef } from 'angular2/core';
import { EventEmitter, ViewContainerRef, ChangeDetectorRef } from 'angular2/core';
import { PaginationService } from "./pagination-service";

@@ -7,23 +7,29 @@ export interface IPage {

}
export declare class PaginationControlsCmp {
export declare class PaginationControlsBase {
private service;
private viewContainer;
id: string;
maxSize: number;
directionLinks: boolean;
autoHide: boolean;
pageChange: EventEmitter<number>;
customTemplate: any;
private changeSub;
pages: IPage[];
constructor(service: PaginationService, viewContainer: ViewContainerRef);
private updatePages();
displayDefaultTemplate(): boolean;
/**
* Set up the subscription to the PaginationService.change observable.
* The api object provides data and methods to be used in the template.
* The reason it is done this way, rather than just using instance members, is so that we can
* unify the way the component and directive templates access them.
*/
private ngOnInit();
private ngAfterContentInit();
private ngOnChanges();
private ngOnDestroy();
api: {
pages: any[];
directionLinks: boolean;
autoHide: boolean;
maxSize: number;
getCurrent: () => number;
setCurrent: (val: any) => void;
previous: () => void;
next: () => void;
isFirstPage: () => boolean;
isLastPage: () => boolean;
};
private changeSub;
constructor(service: PaginationService);
updatePages(): void;
ngOnInit(): void;
ngOnChanges(): void;
ngOnDestroy(): void;
/**

@@ -37,5 +43,12 @@ * Set the current page number.

getCurrent(): number;
isFirstPage(): boolean;
isLastPage(): boolean;
/**
* Returns the last page number
*/
getLastPage(): number;
/**
* Checks that the instance.currentPage property is within bounds for the current page range.
* If not, return a correct value for currentPage, or the current value if OK.
*/
private outOfBoundCorrection(instance);
/**
* Returns an array of IPage objects to use in the pagination controls.

@@ -50,1 +63,24 @@ */

}
export declare class PaginationControlsDirective extends PaginationControlsBase {
private viewContainer;
private cdr;
id: string;
maxSize: number;
directionLinks: boolean;
autoHide: boolean;
pageChange: EventEmitter<number>;
customTemplate: any;
private templateView;
constructor(service: PaginationService, viewContainer: ViewContainerRef, cdr: ChangeDetectorRef);
ngOnInit(): void;
ngAfterViewInit(): void;
}
export declare class PaginationControlsCmp extends PaginationControlsBase {
id: string;
maxSize: number;
directionLinks: boolean;
autoHide: boolean;
pageChange: EventEmitter<number>;
constructor(service: PaginationService);
}
export declare const PAGINATION_DIRECTIVES: (typeof PaginationControlsDirective | typeof PaginationControlsCmp)[];

@@ -0,1 +1,6 @@

var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {

@@ -11,18 +16,27 @@ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;

var core_1 = require('angular2/core');
var common_1 = require('angular2/common');
var lang_1 = require('angular2/src/facade/lang');
var pagination_service_1 = require("./pagination-service");
var DEFAULT_TEMPLATE = "\n <ul class=\"pagination\" role=\"navigation\" aria-label=\"Pagination\" *ngIf=\"displayDefaultTemplate()\">\n\n <li class=\"pagination-previous\" [class.disabled]=\"isFirstPage()\" *ngIf=\"directionLinks\">\n <a *ngIf=\"1 < getCurrent()\" (click)=\"setCurrent(getCurrent() - 1)\" aria-label=\"Next page\">\n Previous <span class=\"show-for-sr\">page</span>\n </a>\n <span *ngIf=\"isFirstPage()\">Previous <span class=\"show-for-sr\">page</span></span>\n </li>\n\n <li [class.current]=\"getCurrent() === page.value\" *ngFor=\"#page of pages\">\n <a (click)=\"setCurrent(page.value)\" *ngIf=\"getCurrent() !== page.value\">\n <span class=\"show-for-sr\">Page</span>\n <span>{{ page.label }}</span>\n </a>\n <div *ngIf=\"getCurrent() === page.value\">\n <span class=\"show-for-sr\">You're on page</span>\n <span>{{ page.label }}</span>\n </div>\n </li>\n\n <li class=\"pagination-next\" [class.disabled]=\"isLastPage()\" *ngIf=\"directionLinks\">\n <a *ngIf=\"!isLastPage()\" (click)=\"setCurrent(getCurrent() + 1)\" aria-label=\"Next page\">\n Next <span class=\"show-for-sr\">page</span>\n </a>\n <span *ngIf=\"isLastPage()\">Next <span class=\"show-for-sr\">page</span></span>\n </li>\n\n </ul>\n ";
function getTemplate() {
return pagination_service_1.PaginationService.template || DEFAULT_TEMPLATE;
}
var PaginationControlsCmp = (function () {
function PaginationControlsCmp(service, viewContainer) {
var template_1 = require('./template');
var PaginationControlsBase = (function () {
function PaginationControlsBase(service) {
var _this = this;
this.service = service;
this.viewContainer = viewContainer;
this.maxSize = 7;
this.directionLinks = true;
this.autoHide = false;
this.pageChange = new core_1.EventEmitter();
this.pages = [];
/**
* The api object provides data and methods to be used in the template.
* The reason it is done this way, rather than just using instance members, is so that we can
* unify the way the component and directive templates access them.
*/
this.api = {
pages: [],
directionLinks: true,
autoHide: false,
maxSize: 7,
getCurrent: function () { return _this.getCurrent(); },
setCurrent: function (val) { return _this.setCurrent(val); },
previous: function () { return _this.setCurrent(_this.getCurrent() - 1); },
next: function () { return _this.setCurrent(_this.getCurrent() + 1); },
isFirstPage: function () { return _this.getCurrent() === 1; },
isLastPage: function () { return _this.getLastPage() === _this.getCurrent(); }
};
this.changeSub = this.service.change

@@ -35,16 +49,11 @@ .subscribe(function (id) {

}
PaginationControlsCmp.prototype.updatePages = function () {
PaginationControlsBase.prototype.updatePages = function () {
var inst = this.service.getInstance(this.id);
this.pages = this.createPageArray(inst.currentPage, inst.itemsPerPage, inst.totalItems, this.maxSize);
};
PaginationControlsCmp.prototype.displayDefaultTemplate = function () {
if (this.customTemplate !== null) {
return false;
this.api.pages = this.createPageArray(inst.currentPage, inst.itemsPerPage, inst.totalItems, this.api.maxSize);
var correctedCurrentPage = this.outOfBoundCorrection(inst);
if (correctedCurrentPage !== inst.currentPage) {
this.setCurrent(correctedCurrentPage);
}
return !this.autoHide || 1 < this.pages.length;
};
/**
* Set up the subscription to the PaginationService.change observable.
*/
PaginationControlsCmp.prototype.ngOnInit = function () {
PaginationControlsBase.prototype.ngOnInit = function () {
if (this.id === undefined) {

@@ -54,12 +63,6 @@ this.id = this.service.defaultId;

};
PaginationControlsCmp.prototype.ngAfterContentInit = function () {
if (this.customTemplate !== null) {
this.viewContainer.createEmbeddedView(this.customTemplate);
}
};
PaginationControlsCmp.prototype.ngOnChanges = function () {
PaginationControlsBase.prototype.ngOnChanges = function () {
this.updatePages();
};
PaginationControlsCmp.prototype.ngOnDestroy = function () {
// TODO: do i need to manually clean these up??? What's the difference between unsubscribe() and remove()
PaginationControlsBase.prototype.ngOnDestroy = function () {
this.changeSub.unsubscribe();

@@ -70,5 +73,4 @@ };

*/
PaginationControlsCmp.prototype.setCurrent = function (page) {
this.service.setCurrentPage(this.id, page);
this.pageChange.emit(this.service.getCurrentPage(this.id));
PaginationControlsBase.prototype.setCurrent = function (page) {
this.pageChange.emit(page);
};

@@ -78,16 +80,30 @@ /**

*/
PaginationControlsCmp.prototype.getCurrent = function () {
PaginationControlsBase.prototype.getCurrent = function () {
return this.service.getCurrentPage(this.id);
};
PaginationControlsCmp.prototype.isFirstPage = function () {
return this.getCurrent() === 1;
};
PaginationControlsCmp.prototype.isLastPage = function () {
/**
* Returns the last page number
*/
PaginationControlsBase.prototype.getLastPage = function () {
var inst = this.service.getInstance(this.id);
return Math.ceil(inst.totalItems / inst.itemsPerPage) === inst.currentPage;
return Math.ceil(inst.totalItems / inst.itemsPerPage);
};
/**
* Checks that the instance.currentPage property is within bounds for the current page range.
* If not, return a correct value for currentPage, or the current value if OK.
*/
PaginationControlsBase.prototype.outOfBoundCorrection = function (instance) {
var totalPages = Math.ceil(instance.totalItems / instance.itemsPerPage);
if (totalPages < instance.currentPage) {
return totalPages;
}
else if (instance.currentPage < 1) {
return 1;
}
return instance.currentPage;
};
/**
* Returns an array of IPage objects to use in the pagination controls.
*/
PaginationControlsCmp.prototype.createPageArray = function (currentPage, itemsPerPage, totalItems, paginationRange) {
PaginationControlsBase.prototype.createPageArray = function (currentPage, itemsPerPage, totalItems, paginationRange) {
// paginationRange could be a string if passed from attribute, so cast to number.

@@ -126,3 +142,3 @@ paginationRange = +paginationRange;

*/
PaginationControlsCmp.prototype.calculatePageNumber = function (i, currentPage, paginationRange, totalPages) {
PaginationControlsBase.prototype.calculatePageNumber = function (i, currentPage, paginationRange, totalPages) {
var halfWay = Math.ceil(paginationRange / 2);

@@ -150,36 +166,142 @@ if (i === paginationRange) {

};
return PaginationControlsBase;
})();
exports.PaginationControlsBase = PaginationControlsBase;
var PaginationControlsDirective = (function (_super) {
__extends(PaginationControlsDirective, _super);
function PaginationControlsDirective(service, viewContainer, cdr) {
_super.call(this, service);
this.viewContainer = viewContainer;
this.cdr = cdr;
}
Object.defineProperty(PaginationControlsDirective.prototype, "maxSize", {
set: function (value) {
this.api.maxSize = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PaginationControlsDirective.prototype, "directionLinks", {
set: function (value) {
this.api.directionLinks = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PaginationControlsDirective.prototype, "autoHide", {
set: function (value) {
this.api.autoHide = value;
},
enumerable: true,
configurable: true
});
PaginationControlsDirective.prototype.ngOnInit = function () {
// we need to detach the change detector initially, to prevent a
// "changed after checked" error.
this.cdr.detach();
};
PaginationControlsDirective.prototype.ngAfterViewInit = function () {
var _this = this;
if (this.customTemplate !== null) {
this.templateView = this.viewContainer.createEmbeddedView(this.customTemplate);
this.templateView.setLocal('paginationApi', this.api);
}
setTimeout(function () { return _this.cdr.reattach(); });
};
__decorate([
core_1.Input(),
__metadata('design:type', String)
], PaginationControlsCmp.prototype, "id", void 0);
], PaginationControlsDirective.prototype, "id", void 0);
__decorate([
core_1.Input(),
__metadata('design:type', Number)
], PaginationControlsCmp.prototype, "maxSize", void 0);
__metadata('design:type', Number),
__metadata('design:paramtypes', [Number])
], PaginationControlsDirective.prototype, "maxSize", null);
__decorate([
core_1.Input(),
__metadata('design:type', Boolean)
], PaginationControlsCmp.prototype, "directionLinks", void 0);
__metadata('design:type', Boolean),
__metadata('design:paramtypes', [Boolean])
], PaginationControlsDirective.prototype, "directionLinks", null);
__decorate([
core_1.Input(),
__metadata('design:type', Boolean)
], PaginationControlsCmp.prototype, "autoHide", void 0);
__metadata('design:type', Boolean),
__metadata('design:paramtypes', [Boolean])
], PaginationControlsDirective.prototype, "autoHide", null);
__decorate([
core_1.Output(),
__metadata('design:type', core_1.EventEmitter)
], PaginationControlsCmp.prototype, "pageChange", void 0);
], PaginationControlsDirective.prototype, "pageChange", void 0);
__decorate([
core_1.ContentChild(core_1.TemplateRef),
__metadata('design:type', Object)
], PaginationControlsCmp.prototype, "customTemplate", void 0);
], PaginationControlsDirective.prototype, "customTemplate", void 0);
PaginationControlsDirective = __decorate([
core_1.Directive({
selector: '[paginationControls]'
}),
__metadata('design:paramtypes', [pagination_service_1.PaginationService, core_1.ViewContainerRef, core_1.ChangeDetectorRef])
], PaginationControlsDirective);
return PaginationControlsDirective;
})(PaginationControlsBase);
exports.PaginationControlsDirective = PaginationControlsDirective;
var PaginationControlsCmp = (function (_super) {
__extends(PaginationControlsCmp, _super);
function PaginationControlsCmp(service) {
_super.call(this, service);
}
Object.defineProperty(PaginationControlsCmp.prototype, "maxSize", {
set: function (value) {
this.api.maxSize = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PaginationControlsCmp.prototype, "directionLinks", {
set: function (value) {
this.api.directionLinks = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PaginationControlsCmp.prototype, "autoHide", {
set: function (value) {
this.api.autoHide = value;
},
enumerable: true,
configurable: true
});
__decorate([
core_1.Input(),
__metadata('design:type', String)
], PaginationControlsCmp.prototype, "id", void 0);
__decorate([
core_1.Input(),
__metadata('design:type', Number),
__metadata('design:paramtypes', [Number])
], PaginationControlsCmp.prototype, "maxSize", null);
__decorate([
core_1.Input(),
__metadata('design:type', Boolean),
__metadata('design:paramtypes', [Boolean])
], PaginationControlsCmp.prototype, "directionLinks", null);
__decorate([
core_1.Input(),
__metadata('design:type', Boolean),
__metadata('design:paramtypes', [Boolean])
], PaginationControlsCmp.prototype, "autoHide", null);
__decorate([
core_1.Output(),
__metadata('design:type', core_1.EventEmitter)
], PaginationControlsCmp.prototype, "pageChange", void 0);
PaginationControlsCmp = __decorate([
core_1.Component({
selector: 'pagination-controls',
template: getTemplate(),
directives: [common_1.CORE_DIRECTIVES]
template: template_1.DEFAULT_TEMPLATE,
styles: [template_1.DEFAULT_STYLES]
}),
__metadata('design:paramtypes', [pagination_service_1.PaginationService, core_1.ViewContainerRef])
__metadata('design:paramtypes', [pagination_service_1.PaginationService])
], PaginationControlsCmp);
return PaginationControlsCmp;
})();
})(PaginationControlsBase);
exports.PaginationControlsCmp = PaginationControlsCmp;
exports.PAGINATION_DIRECTIVES = lang_1.CONST_EXPR([PaginationControlsDirective, PaginationControlsCmp]);

@@ -31,4 +31,2 @@ import { EventEmitter } from 'angular2/core';

defaultId: string;
static templateUrl: string;
static template: string;
register(instance: IPaginationInstance): void;

@@ -35,0 +33,0 @@ /**

@@ -90,2 +90,3 @@ var core_1 = require('angular2/core');

}
return {};
};

@@ -92,0 +93,0 @@ /**

{
"name": "ng2-pagination",
"version": "0.0.1-alpha.13",
"version": "0.0.1-beta.1",
"description": "Pagination for Angular2",

@@ -8,3 +8,6 @@ "main": "index.js",

"build": "node node_modules/typescript/bin/tsc",
"test": "node node_modules/karma/bin/karma start karma.conf.js"
"test": "karma start karma.conf.js",
"demo:watch": "webpack --progress --colors --watch",
"demo:dist": "webpack --progress --colors --dist",
"publish": "npm run build && npm run demo:dist"
},

@@ -30,5 +33,8 @@ "files": [

"devDependencies": {
"angular2": "^2.0.0-beta.0",
"angular2": "^2.0.0-beta.6",
"bulma": "^0.0.14",
"es6-promise": "^3.0.2",
"es6-shim": "^0.33.13",
"highlight.js": "^9.1.0",
"html-loader": "^0.4.3",
"jasmine-core": "^2.4.1",

@@ -46,4 +52,3 @@ "karma": "^0.13.15",

},
"dependencies": {
}
"dependencies": {}
}
# Angular2 Pagination
This is a **work-in-progress** port of my [angular-utils-pagination](https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination)
module from Angular 1.x to Angular 2.
This is a port of my [angular-utils-pagination](https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination)
module from Angular 1.x to Angular 2. Due to fundamental differences in the design of Angular2, the API is different but
the idea is the same - the most simple possible way to add full-featured pagination to an Angular app.
It is not yet well production-tested and is currently missing a few features, but I hope to bring it eventually to full
feature-parity with the 1.x version.
The API will not quite be the same, but it should be significantly simpler and easier to develop than the 1.x version (I hope).
## Demo

@@ -15,9 +11,6 @@

To play with the demo, just clone this repo and start editing the files in the `/demo` folder. The index for the demo is
`index.html` in the root folder.
## Quick Start
## Installation
Requirements: TypeScript 1.6+ (for TS builds), tested with Angular 2.0.0-beta.6+
I am currently working with TypeScript 1.7.3, so these instructions may not work with earlier versions.
```

@@ -27,8 +20,8 @@ npm install ng2-pagination --save

**Note** that currently this module only supports commonjs.
## Example of usage
## Simple Example
```TypeScript
import {Component} from 'angular2/core';
import {CORE_DIRECTIVES} from 'angular2/common';
import {PaginatePipe, PaginationControlsCmp, PaginationService} from 'ng2-pagination';

@@ -40,8 +33,8 @@

<ul>
<li *ngFor="#item of collection | paginate: [ITEMS_PER_PAGE or CONFIG_OBJECT] "> ... </li>
<li *ngFor="#item of collection | paginate: { itemsPerPage: 10, currentPage: p }"> ... </li>
<ul>
<pagination-controls></pagination-controls>
<pagination-controls (pageChange)="p = $event"></pagination-controls>
`,
directives: [CORE_DIRECTIVES, PaginationControlsCmp],
directives: [PaginationControlsCmp],
pipes: [PaginatePipe],

@@ -52,12 +45,4 @@ providers: [PaginationService]

public collection: any[];
public collection: any[] = someArrayOfThings;
constructor(private dataService: DataService) {
}
ngInit() {
this.dataService.getCollection()
.subscribe(result => this.collection = result);
}
}

@@ -70,35 +55,20 @@ ```

The PaginatePipe should be placed at the end of an NgFor expression. It accepts a single argument, which should be
either a `number` or an object confirming to `IPaginationInstance`. If the argument is a number, the number sets the
value of `itemsPerPage`.
The PaginatePipe should be placed at the end of an NgFor expression. It accepts a single argument, an object confirming
to `IPaginationInstance`. The following config options are available:
Using an object allows some more advanced configuration. The following config options are available:
```HTML
<element *ngFor="#item of collection | paginate: { id: 'foo'
itemsPerPage: pageSize
currentPage: p
totalItems: total }">...</element>
```JavaScript
interface IPaginationInstance {
/**
* An optional ID for the pagination instance. Only useful if you wish to
* have more than once instance at a time in a given component.
*/
id?: string;
/**
* The number of items per paginated page.
*/
itemsPerPage: number;
/**
* The current (active) page.
*/
currentPage: number;
/**
* The total number of items in the collection. Only useful when
* doing server-side paging, where the collection size is limited
* to a single page returned by the server API.
*
* For in-memory paging, this property should not be set, as it
* will be automatically set to the value of collection.length.
*/
totalItems?: number;
}
```
* **`itemsPerPage`** [`number` - **required**] The number of items to display on each page.
* **`currentPage`** [`number` - **required**] The current (active) page number.
* **`id`** [`string`] If you need to support more than one instance of pagination at a time, set the `id` and ensure it
matches the id set in the PaginatePipe config (see below).
* **`totalItems`** [`number`] The total number of items in the collection. Only useful when doing server-side paging,
where the collection size is limited to a single page returned by the server API. For in-memory paging,
this property should not be set, as it will be automatically set to the value of collection.length.

@@ -109,4 +79,5 @@ ### PaginationControlsCmp

<pagination-controls id="some_id"
(change)="pageChanged($event)"
(pageChange)="pageChanged($event)"
maxSize="9"
directionLinks="true"
autoHide="true">

@@ -116,32 +87,112 @@ </pagination-controls>

* **`id`** [string] If you need to support more than one instance of pagination at a time, set the `id` and ensure it
* **`id`** [`string`] If you need to support more than one instance of pagination at a time, set the `id` and ensure it
matches the id set in the PaginatePipe config.
* **`change`** [function] The function specified will be invoked whenever the page changes via a click on one of the
pagination controls. The `$event` argument will be the number of the new page.
* **maxSize** [number] Defines the maximum number of page links to display. Default is `7`.
* **`autoHide`** [boolean] If set to `true`, the pagination controls will not be displayed when all items in the
collection fit onto the first page. Default is `false`
* **`pageChange`** [`event handler`] The expression specified will be invoked whenever the page changes via a click on one of the
pagination controls. The `$event` argument will be the number of the new page. This should be used to update the value of
the `currentPage` variable which was passed to the `PaginatePipe`.
* **`maxSize`** [`number`] Defines the maximum number of page links to display. Default is `7`.
* **`directionLinks`** [`boolean`] If set to `false`, the "previous" and "next" links will not be displayed. Default is `true`.
* **`autoHide`** [`boolean`] If set to `true`, the pagination controls will not be displayed when all items in the
collection fit onto the first page. Default is `false`.
## To Do
## Server-Side Paging
The following features from the 1.x version have not yet been implemented:
In many cases - for example when working with very large data-sets - we do not want to work with the full collection
in memory, and use some kind of server-side paging, where the server sends just a single page at a time.
- ~~Handling of multiple independent instances within the same component.~~
- ~~Server-side paging support~~
- ~~Page-change event support~~
- Custom template support
- ~~Various style options for the pagination controls template~~
- Full test suite
This scenario is supported by ng2-pagination by using the `totalItems` config option.
I have written a few tests, but right now I am waiting for the Angular team to publish some guidelines on how
best to test components.
Given a server response json object like this:
```
{
"count": 14453,
"data": [
{ /* item 1 */ },
{ /* item 2 */ },
{ /* item 3 */ },
{ /* ... */ },
{ /* item 10 */ }
]
}
```
we should pass the value of `count` to the `PaginatePipe` as the `totalItems` argument:
```HTML
<li *ngFor="#item of collection | paginate: { itemsPerPage: 10, currentPage: p, totalItems: res.count }">...</li>
```
This will allow the correct number of page links to be calculated. To see a complete example of this (including
using the `async` pipe), see the [demo](http://michaelbromley.github.io/ng2-pagination/).
## Custom Templates
The `PaginationControlsCmp` component has a built-in default template and styles based on the [Foundation 6 pagination
component](http://foundation.zurb.com/sites/docs/pagination.html).
To use a custom template, you should instead use the `PaginationControlsDirective`:
```HTML
<template paginationControls #p="paginationApi" (pageChange)="currentPage = $event">
<div class="custom-pagination">
<div class="pagination-previous" [class.disabled]="p.isFirstPage()">
<a *ngIf="!p.isFirstPage()" (click)="p.previous()"> < </a>
</div>
<div *ngFor="#page of p.pages" [class.current]="p.getCurrent() === page.value">
<a (click)="p.setCurrent(page.value)" *ngIf="p.getCurrent() !== page.value">
<span>{{ page.label }}</span>
</a>
<div *ngIf="p.getCurrent() === page.value">
<span>{{ page.label }}</span>
</div>
</div>
<div class="pagination-next" [class.disabled]="p.isLastPage()" *ngIf="p.directionLinks">
<a *ngIf="!p.isLastPage()" (click)="p.next()"> > </a>
</div>
</div>
</template>
```
The key thing to note here is `#p="paginationApi` - this provides a local variable, `p`, which can be used in the
template to access the `paginationApi` members, which are explained below:
* **`pages`** [`{ label: string, value: any }[]`] Array of page objects containing the page number and label.
* **`directionLinks`** [`boolean`] Corresponds to the value of `directionLinks` which is passed to the directive.
* **`autoHide`** [`boolean`] Corresponds to the value of `autoHide` which is passed to the directive.
* **`maxSize`** [`number`] Corresponds to the value of `maxSize` which is passed to the directive.
* **`getCurrent()`** [`() => number`] Returns the current page number.
* **`setCurrent(val)`** [`(val: number) => void`] Triggers the `pageChange` event with the page number passed as `val`.
* **`previous()`** [`() -> void`] Sets current page to previous, triggering the `pageChange` event.
* **`next()`** [`() -> void`] Sets current page to next, triggering the `pageChange` event.
* **`isFirstPage()`** [`() => boolean`] Returns true if the current page is the first page.
* **`isLastPage()`** [`() => boolean`] Returns true if the current page is the last page/
## Build
To build, first run `npm install` to get all the dev dependencies. Then you can use the `npm run build` script to
compile the TypeScript and generate the definition files. `npm run test` will fire up Karma with the Webpack
plugin to run the tests.
Requires globally-installed node, npm, typings.
```
npm install
typings install
npm run test // Karma unit tests
npm run demo:watch // Build the demo app and watch
```
More complete contributing instructions to follow.
## Dart Version
For Dart users, there is a Dart port available here: https://github.com/laagland/ng2-dart-pagination. Note that this
version was written and is maintained by a different author and may not be up-to-date with this repo.
## License
MIT
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc