Skip to content

Commit

Permalink
feat(footer): add row selection count to the footer component
Browse files Browse the repository at this point in the history
  • Loading branch information
ghiscoding committed Apr 22, 2021
1 parent e0b092e commit 5604669
Show file tree
Hide file tree
Showing 14 changed files with 156 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ const mockGrid = {
setSelectedRows: jest.fn(),
onRendered: jest.fn(),
onScroll: jest.fn(),
onDataviewCreated: new Slick.Event(),
onSelectedRowsChanged: new Slick.Event(),
};

const mockSlickCoreImplementation = jest.fn().mockImplementation(() => (mockSlickCore));
Expand Down Expand Up @@ -1441,6 +1441,7 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () =
expect(component.showCustomFooter).toBeTrue();
expect(component.customFooterOptions).toEqual({
dateFormat: 'yyyy-MM-dd, hh:mm aaaaa\'m\'',
hideRowSelectionCount: false,
hideLastUpdateTimestamp: true,
hideTotalItemCount: false,
footerHeight: 20,
Expand All @@ -1449,6 +1450,8 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () =
metricTexts: {
items: 'items',
itemsKey: 'ITEMS',
itemsSelected: 'items selected',
itemsSelectedKey: 'ITEMS_SELECTED',
of: 'of',
ofKey: 'OF',
},
Expand Down Expand Up @@ -1479,6 +1482,7 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () =
expect(component.showCustomFooter).toBeTrue();
expect(component.customFooterOptions).toEqual({
dateFormat: 'yyyy-MM-dd, hh:mm aaaaa\'m\'',
hideRowSelectionCount: false,
hideLastUpdateTimestamp: true,
hideTotalItemCount: false,
footerHeight: 20,
Expand All @@ -1487,6 +1491,8 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () =
metricTexts: {
items: 'some items',
itemsKey: 'ITEMS',
itemsSelected: 'items selected',
itemsSelectedKey: 'ITEMS_SELECTED',
lastUpdate: 'some last update',
of: 'some of',
ofKey: 'OF',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ import {
} from '../../extensions';
import * as utilities from '../../services/utilities';

declare const Slick: any;

function removeExtraSpaces(text: string) {
return `${text}`.replace(/\s{2,}/g, '');
}

const mockConvertParentChildArray = jest.fn();
// @ts-ignore
utilities.convertParentChildArrayToHierarchicalView = mockConvertParentChildArray;
Expand Down Expand Up @@ -306,4 +312,72 @@ describe('App Component', () => {
}, 10);
});
});

describe('Custom Footer', () => {
it('should display 1 items selected on the left side footer section after triggering "onSelectedRowsChanged" event', () => {
const mockColDefs = [{ id: 'name', field: 'name', editor: undefined, internalColumnEditor: {} }];

component.gridId = 'grid1';
component.gridOptions = {
enablePagination: false,
showCustomFooter: true,
enableCheckboxSelector: true,
customFooterOptions: {
hideRowSelectionCount: false
}
} as GridOption;
fixture.detectChanges();
component.columnDefinitions = mockColDefs;
component.grid.setSelectionModel(new Slick.CellSelectionModel());
component.grid.onSelectedRowsChanged.notify({ rows: [1], previousSelectedRows: [] });
fixture.detectChanges();

const gridContainerElm = document.querySelector('.slickgrid-container') as HTMLDivElement;
const gridPaneElm = document.querySelector('.gridPane') as HTMLDivElement;
const footerContainerElm = document.querySelector('div.slick-custom-footer') as HTMLDivElement;
const leftFooterElm = document.querySelector('div.slick-custom-footer > div.left-footer') as HTMLSpanElement;
const rightFooterElm = document.querySelector('div.slick-custom-footer > div.metrics') as HTMLSpanElement;

expect(gridPaneElm.id).toBe('slickGridContainer-grid1');
expect(gridContainerElm.id).toBe('grid1');
expect(footerContainerElm).toBeTruthy();
expect(rightFooterElm).toBeTruthy();
expect(leftFooterElm).toBeTruthy();
expect(component.gridOptions.customFooterOptions!.leftFooterText).toBe('1 items selected');
expect(leftFooterElm.innerHTML).toContain('1 items selected');
});

it('should not not display row selection count after triggering "onSelectedRowsChanged" event when "hideRowSelectionCount" is set to True', () => {
const mockColDefs = [{ id: 'name', field: 'name', editor: undefined, internalColumnEditor: {} }];

component.gridId = 'grid1';
component.gridOptions = {
enablePagination: false,
showCustomFooter: true,
enableCheckboxSelector: true,
customFooterOptions: {
hideRowSelectionCount: true
}
} as GridOption;
fixture.detectChanges();
component.columnDefinitions = mockColDefs;
component.grid.setSelectionModel(new Slick.CellSelectionModel());
component.grid.onSelectedRowsChanged.notify({ rows: [1], previousSelectedRows: [] });
fixture.detectChanges();

const gridContainerElm = document.querySelector('.slickgrid-container') as HTMLDivElement;
const gridPaneElm = document.querySelector('.gridPane') as HTMLDivElement;
const footerContainerElm = document.querySelector('div.slick-custom-footer') as HTMLDivElement;
const leftFooterElm = document.querySelector('div.slick-custom-footer > div.left-footer') as HTMLSpanElement;
const rightFooterElm = document.querySelector('div.slick-custom-footer > div.metrics') as HTMLSpanElement;

expect(gridPaneElm.id).toBe('slickGridContainer-grid1');
expect(gridContainerElm.id).toBe('grid1');
expect(footerContainerElm).toBeTruthy();
expect(rightFooterElm).toBeTruthy();
expect(leftFooterElm).toBeTruthy();
expect(component.gridOptions.customFooterOptions!.leftFooterText).toBeFalsy();
expect(leftFooterElm.innerHTML).toBeFalsy();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,15 @@ describe('App Component', () => {
translate.setTranslation('fr', {
ITEMS: 'éléments',
ITEMS_PER_PAGE: 'éléments par page',
ITEMS_SELECTED: 'éléments sélectionnés',
OF: 'de',
PAGE: 'Page',
PAGE_X_OF_Y: 'page {{x}} de {{y}}',
});
translate.setTranslation('en', {
ITEMS: 'items',
ITEMS_PER_PAGE: 'items per page',
ITEMS_SELECTED: 'items selected',
OF: 'of',
PAGE: 'Page',
PAGE_X_OF_Y: 'page {{x}} of {{y}}',
Expand Down Expand Up @@ -114,7 +116,7 @@ describe('App Component', () => {
component.gridOptions = { enableTranslate: true } as GridOption;
fixture.detectChanges();

const elm = document.querySelector('.slick-pagination');
const elm = document.querySelector('.slick-pagination') as HTMLDivElement;
const pageInfoFromTo = fixture.debugElement.query(By.css('.page-info-from-to')).nativeElement;
const pageInfoTotalItems = fixture.debugElement.query(By.css('.page-info-total-items')).nativeElement;

Expand All @@ -132,15 +134,15 @@ describe('App Component', () => {

expect(selectElement.value).toBe('10');
expect(selectElement.selectedIndex).toBe(1);
const optionElement = selectElement.selectedOptions.item(0);
const optionElement = selectElement.selectedOptions.item(0) as HTMLOptionElement;
expect(optionElement.value).toBe('10');
});

it('should create a the Slick-Pagination component in the DOM and expect different locale when changed', () => {
translate.use('en');
fixture.detectChanges();

const elm = document.querySelector('.slick-pagination');
const elm = document.querySelector('.slick-pagination') as HTMLDivElement;
const pageInfoFromTo = fixture.debugElement.query(By.css('.page-info-from-to')).nativeElement;
const pageInfoTotalItems = fixture.debugElement.query(By.css('.page-info-total-items')).nativeElement;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@
<!-- Custom Footer section under the grid -->
<div *ngIf="showCustomFooter && customFooterOptions" class="slick-custom-footer" style="width: 100%;"
[style.height]="customFooterOptions?.footerHeight || 20">
<div class="left-footer" [ngClass]="customFooterOptions.leftContainerClass">
{{customFooterOptions.leftFooterText}}
</div>
<div class="left-footer" [ngClass]="customFooterOptions.leftContainerClass">{{customFooterOptions.leftFooterText}}</div>

<div class="right-footer metrics" [ngClass]="customFooterOptions.rightContainerClass"
*ngIf="metrics && !customFooterOptions.hideMetrics">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1178,8 +1178,10 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn
customFooterOptions.metricTexts = customFooterOptions.metricTexts || {};
customFooterOptions.metricTexts.lastUpdate = customFooterOptions.metricTexts.lastUpdate || this.locales && this.locales.TEXT_LAST_UPDATE || 'TEXT_LAST_UPDATE';
customFooterOptions.metricTexts.items = customFooterOptions.metricTexts.items || this.locales && this.locales.TEXT_ITEMS || 'TEXT_ITEMS';
customFooterOptions.metricTexts.itemsSelected = customFooterOptions.metricTexts.itemsSelected || this.locales && this.locales.TEXT_ITEMS_SELECTED || 'TEXT_ITEMS_SELECTED';
customFooterOptions.metricTexts.of = customFooterOptions.metricTexts.of || this.locales && this.locales.TEXT_OF || 'TEXT_OF';
}
this.registerOnSelectedRowsChangedWhenEnabled(this.gridOptions.customFooterOptions);

// we will display the custom footer only when there's no Pagination
if (!this.gridOptions.enablePagination && !this._isPaginationInitialized) {
Expand All @@ -1190,6 +1192,23 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn
}
}

/**
* When user has row selections enabled and does not have any custom text shown on the left side footer,
* we will show the row selection count on the bottom left side of the footer (by subscribing to the SlickGrid `onSelectedRowsChanged` event).
* @param customFooterOptions
*/
private registerOnSelectedRowsChangedWhenEnabled(customFooterOptions?: CustomFooterOption) {
const isRowSelectionEnabled = this.gridOptions.enableCheckboxSelector || this.gridOptions.enableRowSelection;
if (isRowSelectionEnabled && customFooterOptions && (!customFooterOptions.hideRowSelectionCount && !customFooterOptions.leftFooterText)) {
const selectedCountText = customFooterOptions.metricTexts?.itemsSelected ?? this.locales?.TEXT_ITEMS_SELECTED ?? 'TEXT_ITEMS_SELECTED';
customFooterOptions.leftFooterText = `0 ${selectedCountText}`;

this._eventHandler.subscribe(this.grid.onSelectedRowsChanged, (_e: any, args: { rows: number[]; previousSelectedRows: number[]; }) => {
customFooterOptions.leftFooterText = `${args.rows.length || 0} ${selectedCountText}`;
});
}
}

private treeDataSortComparer(flatDataset: any[]): any[] {
const dataViewIdIdentifier = this.gridOptions && this.gridOptions.datasetIdPropertyName || 'id';
const treeDataOpt: TreeDataOption = this.gridOptions && this.gridOptions.treeDataOptions || { columnId: '' };
Expand Down
1 change: 1 addition & 0 deletions src/app/modules/angular-slickgrid/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export class Constants {
TEXT_HIDE_COLUMN: 'Hide Column',
TEXT_ITEMS: 'items',
TEXT_ITEMS_PER_PAGE: 'items per page',
TEXT_ITEMS_SELECTED: 'items selected',
TEXT_OF: 'of',
TEXT_OK: 'OK',
TEXT_LAST_UPDATE: 'Last Update',
Expand Down
5 changes: 4 additions & 1 deletion src/app/modules/angular-slickgrid/global-grid-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export const GlobalGridOptions: Partial<GridOption> = {
},
customFooterOptions: {
dateFormat: 'yyyy-MM-dd, hh:mm aaaaa\'m\'',
hideRowSelectionCount: false,
hideTotalItemCount: false,
hideLastUpdateTimestamp: true,
footerHeight: 20,
Expand All @@ -61,9 +62,11 @@ export const GlobalGridOptions: Partial<GridOption> = {
metricSeparator: '|',
metricTexts: {
items: 'items',
of: 'of',
itemsKey: 'ITEMS',
of: 'of',
ofKey: 'OF',
itemsSelected: 'items selected',
itemsSelectedKey: 'ITEMS_SELECTED'
}
},
dataView: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { MetricTexts } from './metricTexts.interface';

export interface CustomFooterOption {
/** Optionally pass some text to be displayed on the left side (in the "left-footer" css class) */
leftFooterText?: string;
Expand All @@ -11,6 +13,12 @@ export interface CustomFooterOption {
/** Defaults to 20, height of the Custom Footer in pixels (this is required and is used by the auto-resizer) */
footerHeight?: number;

/**
* Defaults to false, which will hide the selected rows count on the bottom left of the footer.
* NOTE: if users defined a `leftFooterText`, then the selected rows count will NOT show up.
*/
hideRowSelectionCount?: boolean;

/** Defaults to false, do we want to hide the last update timestamp (endTime)? */
hideLastUpdateTimestamp?: boolean;

Expand All @@ -27,27 +35,7 @@ export interface CustomFooterOption {
metricSeparator?: string;

/** Text shown in the custom footer on the far right for the metrics */
metricTexts?: {
/** Defaults to empty string, optionally pass a text (Last Update) to display before the metrics endTime timestamp. */
lastUpdate?: string;

/** Defaults to "items", word to display at the end of the metrics to represent the items (e.g. you could change it for "users" or anything else). */
items?: string;

/** Defaults to "of", text word separator to display between the filtered items count and the total unfiltered items count (e.g.: "10 of 100 items"). */
of?: string;

// -- Translation Keys --//

/** Defaults to "ITEMS", translation key used for the word displayed at the end of the metrics to represent the items (e.g. you could change it for "users" or anything else). */
itemsKey?: string;

/** Defaults to empty string, optionally pass a translation key (internally we use "LAST_UPDATE") to display before the metrics endTime timestamp. */
lastUpdateKey?: string;

/** Defaults to "OF", translation key used for the to display between the filtered items count and the total unfiltered items count. */
ofKey?: string;
};
metricTexts?: MetricTexts;

/** CSS class used for the right container */
rightContainerClass?: string;
Expand Down
1 change: 1 addition & 0 deletions src/app/modules/angular-slickgrid/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ export * from './menuItem.interface';
export * from './menuOptionItem.interface';
export * from './menuOptionItemCallbackArgs.interface';
export * from './metrics.interface';
export * from './metricTexts.interface';
export * from './multiColumnSort.interface';
export * from './multipleSelectOption.interface';
export * from './odataOption.interface';
Expand Down
3 changes: 3 additions & 0 deletions src/app/modules/angular-slickgrid/models/locale.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ export interface Locale {
/** Text "items per page" displayed in the Pagination (when enabled) */
TEXT_ITEMS_PER_PAGE?: string;

/** Text "Records Selected" displayed in the Custom Footer */
TEXT_ITEMS_SELECTED?: string;

/** Text "Last Update" displayed in the Footer (when enabled) */
TEXT_LAST_UPDATE?: string;

Expand Down
29 changes: 29 additions & 0 deletions src/app/modules/angular-slickgrid/models/metricTexts.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export type MetricTexts = {
/** Defaults to empty string, optionally pass a text (Last Update) to display before the metrics endTime timestamp. */
lastUpdate?: string;

/** Defaults to "items", word to display at the end of the metrics to represent the items (e.g. you could change it for "users" or anything else). */
items?: string;

/** Defaults to "of", text word separator to display between the filtered items count and the total unfiltered items count (e.g.: "10 of 100 items"). */
of?: string;

/** Defaults to "records selected", text word that is associated to the row selection count. */
itemsSelected?: string;

// --
// Translation Keys
// ------------------

/** Defaults to "ITEMS", translation key used for the word displayed at the end of the metrics to represent the items (e.g. you could change it for "users" or anything else). */
itemsKey?: string;

/** Defaults to empty string, optionally pass a translation key (internally we use "LAST_UPDATE") to display before the metrics endTime timestamp. */
lastUpdateKey?: string;

/** Defaults to "OF", translation key used for the to display between the filtered items count and the total unfiltered items count. */
ofKey?: string;

/** Defaults to "ITEMS_SELECTED", text word that is associated to the row selection count. */
itemsSelectedKey?: string;
};
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export class ResizerService {

// optionally show a custom footer with the data metrics (dataset length and last updated timestamp)
if (bottomPadding && gridOptions.showCustomFooter) {
bottomPadding += gridOptions.customFooterOptions && gridOptions.customFooterOptions.footerHeight || DATAGRID_FOOTER_HEIGHT;
bottomPadding += gridOptions?.customFooterOptions?.footerHeight ?? DATAGRID_FOOTER_HEIGHT;
}

let gridHeight = 0;
Expand Down
1 change: 1 addition & 0 deletions src/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"IN_COLLECTION_SEPERATED_BY_COMMA": "Search items in a collection, must be separated by a comma (a,b)",
"ITEMS": "items",
"ITEMS_PER_PAGE": "items per page",
"ITEMS_SELECTED": "items selected",
"LAST_UPDATE": "Last Update",
"LESS_THAN": "Less than",
"LESS_THAN_OR_EQUAL_TO": "Less than or equal to",
Expand Down
1 change: 1 addition & 0 deletions src/assets/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"INVALID_FLOAT": "Le nombre doit être valide et avoir un maximum de {{maxDecimal}} décimales.",
"ITEMS": "éléments",
"ITEMS_PER_PAGE": "éléments par page",
"ITEMS_SELECTED": "éléments sélectionnés",
"LAST_UPDATE": "Dernière mise à jour",
"LESS_THAN": "Plus petit que",
"LESS_THAN_OR_EQUAL_TO": "Plus petit ou égal à",
Expand Down

0 comments on commit 5604669

Please sign in to comment.