Skip to content
This repository was archived by the owner on Jun 1, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
<div id="slickGridContainer-{{gridId}}" class="gridPane" [style.width]="gridWidthString">
<div attr.id='{{gridId}}' class="slickgrid-container" style="width: 100%" [style.height]="gridHeightString">
</div>
<div attr.id='{{gridId}}' class="slickgrid-container" style="width: 100%" [style.height]="gridHeightString">
</div>

<slick-pagination id="slickPagingContainer-{{gridId}}"
*ngIf="showPagination"
(onPaginationChanged)="paginationChanged($event)"
[dataView]="dataView"
[gridPaginationOptions]="gridPaginationOptions">
</slick-pagination>
<slick-pagination id="slickPagingContainer-{{gridId}}"
*ngIf="showPagination"
(onPaginationChanged)="paginationChanged($event)"
[enableTranslate]="gridOptions.enableTranslate"
[dataView]="dataView"
[grid]="grid"
[options]="paginationOptions"
[locales]="locales"
[totalItems]="totalItems"
[backendServiceApi]="backendServiceApi">
</slick-pagination>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,24 @@ import 'slickgrid/slick.grid';
import 'slickgrid/slick.dataview';

// ...then everything else...
import { AfterViewInit, Component, ElementRef, EventEmitter, Inject, Injectable, Input, Output, OnDestroy, OnInit, Optional } from '@angular/core';
import { AfterViewInit, Component, ElementRef, EventEmitter, Inject, Input, Output, OnDestroy, OnInit, Optional } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';

import { Constants } from '../constants';
import { GlobalGridOptions } from './../global-grid-options';
import { titleCase, unsubscribeAllObservables } from './../services/utilities';
import { executeBackendProcessesCallback, onBackendError } from '../services/backend-utilities';
import {
AngularGridInstance,
BackendServiceApi,
BackendServiceOption,
Column,
ExtensionName,
GraphqlResult,
GridOption,
GridStateChange,
GridStateType,
Locale,
Pagination,
} from './../models/index';
import { FilterFactory } from '../filters/filterFactory';
Expand Down Expand Up @@ -63,7 +67,6 @@ declare var $: any;

const slickgridEventPrefix = 'sg';

@Injectable()
@Component({
selector: 'angular-slickgrid',
templateUrl: './angular-slickgrid.component.html',
Expand Down Expand Up @@ -108,12 +111,15 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn
private _hideHeaderRowAfterPageLoad = false;
dataView: any;
grid: any;
gridPaginationOptions: GridOption;
gridHeightString: string;
gridWidthString: string;
groupingDefinition: any = {};
groupItemMetadataProvider: any;
backendServiceApi: BackendServiceApi;
locales: Locale;
paginationOptions: Pagination;
showPagination = false;
totalItems = 0;
isGridInitialized = false;
subscriptions: Subscription[] = [];

Expand Down Expand Up @@ -234,6 +240,9 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn
// make sure the dataset is initialized (if not it will throw an error that it cannot getLength of null)
this._dataset = this._dataset || [];
this.gridOptions = this.mergeGridOptions(this.gridOptions);
this.paginationOptions = this.gridOptions.pagination;
this.locales = this.gridOptions && this.gridOptions.locales || Constants.locales;
this.backendServiceApi = this.gridOptions && this.gridOptions.backendServiceApi;
this.createBackendApiInternalPostProcessCallback(this.gridOptions);

if (!this.customDataView) {
Expand Down Expand Up @@ -564,10 +573,10 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn
try {
// the processes can be Observables (like HttpClient) or Promises
if (process instanceof Promise && process.then) {
process.then((processResult: GraphqlResult | any) => executeBackendProcessesCallback(startTime, processResult, backendApi, this.gridOptions));
process.then((processResult: GraphqlResult | any) => executeBackendProcessesCallback(startTime, processResult, backendApi, this.gridOptions.pagination.totalItems));
} else if (isObservable(process)) {
process.subscribe(
(processResult: GraphqlResult | any) => executeBackendProcessesCallback(startTime, processResult, backendApi, this.gridOptions),
(processResult: GraphqlResult | any) => executeBackendProcessesCallback(startTime, processResult, backendApi, this.gridOptions.pagination.totalItems),
(error: any) => onBackendError(error, backendApi)
);
}
Expand Down Expand Up @@ -665,24 +674,25 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn
this.grid.render();
}

if (this.gridOptions.backendServiceApi) {
if (this.gridOptions && this.gridOptions.backendServiceApi && this.gridOptions.pagination) {
// do we want to show pagination?
// if we have a backendServiceApi and the enablePagination is undefined, we'll assume that we do want to see it, else get that defined value
this.showPagination = ((this.gridOptions.backendServiceApi && this.gridOptions.enablePagination === undefined) ? true : this.gridOptions.enablePagination) || false;

// before merging the grid options, make sure that it has the totalItems count
// once we have that, we can merge and pass all these options to the pagination component
if (!this.gridOptions.pagination) {
this.gridOptions.pagination = (this.gridOptions.pagination) ? this.gridOptions.pagination : undefined;
}
if (this.gridOptions.pagination && totalCount !== undefined) {
this.gridOptions.pagination.totalItems = totalCount;
}
if (this.gridOptions.presets && this.gridOptions.presets.pagination && this.gridOptions.pagination) {
this.gridOptions.pagination.pageSize = this.gridOptions.presets.pagination.pageSize;
this.gridOptions.pagination.pageNumber = this.gridOptions.presets.pagination.pageNumber;
this.paginationOptions.pageSize = this.gridOptions.presets.pagination.pageSize;
this.paginationOptions.pageNumber = this.gridOptions.presets.pagination.pageNumber;
}
this.gridPaginationOptions = this.mergeGridOptions(this.gridOptions);

// when we have a totalCount use it, else we'll take it from the pagination object
// only update the total items if it's different to avoid refreshing the UI
const totalRecords = totalCount !== undefined ? totalCount : this.gridOptions.pagination.totalItems;
if (totalRecords !== this.totalItems) {
this.totalItems = totalRecords;
}
} else {
// without backend service, we'll assume the total of items is the dataset size
this.totalItems = dataset.length;
}

// resize the grid inside a slight timeout, in case other DOM element changed prior to the resize (like a filter/pagination changed)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="slick-pagination" *ngIf="pager">
<div class="slick-pagination" *ngIf="pager && options">
<div class="slick-pagination-nav">
<nav aria-label="Page navigation">
<ul class="pagination">
Expand Down Expand Up @@ -41,7 +41,7 @@
</div>
<span class="slick-pagination-settings">
<select id="items-per-page-label" [value]="pager?.itemsPerPage" (change)="changeItemPerPage($event)">
<option value="{{pageSize}}" *ngFor="let pageSize of pager?.availablePageSizes;">{{pageSize}}</option>
<option value="{{pageSize}}" *ngFor="let pageSize of options.pageSizes">{{pageSize}}</option>
</select>
<span>{{textItemsPerPage}}</span>,
<span class="slick-pagination-count">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,39 @@ import { AfterViewInit, Component, EventEmitter, Injectable, Input, OnDestroy, O
import { TranslateService } from '@ngx-translate/core';
import { Subscription } from 'rxjs';

import { Constants } from '../constants';
import { GridOption, Locale, Pager, Pagination } from './../models/index';
import { BackendServiceApi, Locale, Pager, Pagination } from './../models/index';
import { PaginationService } from '../services/pagination.service';
import { unsubscribeAllObservables } from '../services/utilities';

@Component({
selector: 'slick-pagination',
templateUrl: './slick-pagination.component.html'
})
@Injectable()
export class SlickPaginationComponent implements AfterViewInit, OnDestroy {
private _gridPaginationOptions: GridOption;
private _isFirstRender = true;
private _locales: Locale;
private _pager: Pager;
private _totalItems: number;
private subscriptions: Subscription[] = [];

@Output() onPaginationChanged = new EventEmitter<Pagination>();
@Input() enableTranslate: boolean;
@Input() options: Pagination;
@Input() dataView: any;
@Input() locales: Locale;
@Input() backendServiceApi: BackendServiceApi;
@Input()
set gridPaginationOptions(gridPaginationOptions: GridOption) {
this._gridPaginationOptions = gridPaginationOptions;
if (this._isFirstRender || !gridPaginationOptions || !gridPaginationOptions.pagination || (gridPaginationOptions.pagination.totalItems !== this.pager.totalItems)) {
this.refreshPagination();
this._isFirstRender = false;
set totalItems(total: number) {
if (this._isFirstRender || this._totalItems === undefined) {
this._isFirstRender = true;
}
this._totalItems = total;
this._isFirstRender = false;
if (this.paginationService) {
this.paginationService.totalItems = total;
}
}
get gridPaginationOptions(): GridOption {
return this._gridPaginationOptions;
get totalItems(): number {
return this._totalItems;
}
@Input() grid: any;

Expand All @@ -44,11 +48,11 @@ export class SlickPaginationComponent implements AfterViewInit, OnDestroy {
constructor(private paginationService: PaginationService, @Optional() private translate: TranslateService) {
// translate all the text using ngx-translate or custom locales
if (translate && translate.onLangChange) {
this.subscriptions.push(this.translate.onLangChange.subscribe(() => this.translateAllUiTexts(this._locales)));
this.subscriptions.push(this.translate.onLangChange.subscribe(() => this.translateAllUiTexts(this.locales)));
}

// translate all the text using ngx-translate or custom locales
this.paginationService.onPaginationRefreshed.subscribe(() => this.translateAllUiTexts(this._locales));
this.paginationService.onPaginationRefreshed.subscribe(() => this.translateAllUiTexts(this.locales));

this.paginationService.onPaginationChanged.subscribe(pager => {
this._pager = pager;
Expand All @@ -74,13 +78,12 @@ export class SlickPaginationComponent implements AfterViewInit, OnDestroy {
}

ngAfterViewInit() {
if (this._gridPaginationOptions && this._gridPaginationOptions.enableTranslate && !this.translate) {
if (this.enableTranslate && !this.translate) {
throw new Error('[Angular-Slickgrid] requires "ngx-translate" to be installed and configured when the grid option "enableTranslate" is enabled.');
}
// get locales provided by user in forRoot or else use default English locales via the Constants
this._locales = this._gridPaginationOptions && this._gridPaginationOptions.locales || Constants.locales;

this.paginationService.init(this.grid, this.dataView, this._gridPaginationOptions);
// Angular throws the infamous "ExpressionChangedAfterItHasBeenCheckedError"
// none of the code refactoring worked to go over the error expect adding a delay, so we'll keep that for now
setTimeout(() => this.paginationService.init(this.grid, this.dataView, this.options, this.backendServiceApi));
}

changeToFirstPage(event: any) {
Expand Down Expand Up @@ -123,13 +126,6 @@ export class SlickPaginationComponent implements AfterViewInit, OnDestroy {
this.subscriptions = unsubscribeAllObservables(this.subscriptions);
}

refreshPagination() {
if (this.paginationService) {
this.paginationService.gridPaginationOptions = this._gridPaginationOptions;
this.paginationService.refreshPagination();
}
}

// --
// private functions
// --------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('backend-utilities', () => {
const now = new Date();
gridOptionMock.backendServiceApi.internalPostProcess = jest.fn();
const spy = jest.spyOn(gridOptionMock.backendServiceApi, 'internalPostProcess');
executeBackendProcessesCallback(now, { data: {} }, gridOptionMock.backendServiceApi, gridOptionMock);
executeBackendProcessesCallback(now, { data: {} }, gridOptionMock.backendServiceApi, 0);

expect(spy).toHaveBeenCalled();
});
Expand Down Expand Up @@ -46,7 +46,7 @@ describe('backend-utilities', () => {
gridOptionMock.pagination = { totalItems: 1, pageSizes: [10, 25], pageSize: 10 };

const spy = jest.spyOn(gridOptionMock.backendServiceApi, 'postProcess');
executeBackendProcessesCallback(now, mockResult, gridOptionMock.backendServiceApi, gridOptionMock);
executeBackendProcessesCallback(now, mockResult, gridOptionMock.backendServiceApi, 1);

expect(spy).toHaveBeenCalledWith(expectaction);
});
Expand Down
Loading