Skip to content

Commit

Permalink
feat(tree): add getItemCount method with optional tree level
Browse files Browse the repository at this point in the history
  • Loading branch information
ghiscoding committed Jun 15, 2021
1 parent d2e5685 commit b3f8f94
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 16 deletions.
Expand Up @@ -41,6 +41,9 @@ export class Example5 {
this.sgb = new Slicker.GridBundle(gridContainerElm, this.columnDefinitions, { ...ExampleGridOptions, ...this.gridOptions });
this.dataset = this.loadData(NB_ITEMS);

// optionally display only the parent items count on the right footer
// this.sgb.slickFooter.rightFooterText = `${this.sgb.treeDataService.getItemCount(0)} parent items`;

// with large dataset you maybe want to show spinner before/after these events: sorting/filtering/collapsing/expanding
this._bindingEventService.bind(gridContainerElm, 'onbeforefilterchange', this.showSpinner.bind(this));
this._bindingEventService.bind(gridContainerElm, 'onfilterchanged', this.hideSpinner.bind(this));
Expand Down Expand Up @@ -125,7 +128,7 @@ export class Example5 {
showCustomFooter: true, // display some metrics in the bottom custom footer
customFooterOptions: {
// optionally display some text on the left footer container
leftFooterText: 'Grid created with <a href="https://github.com/ghiscoding/slickgrid-universal" target="_blank">Slickgrid-Universal</a>',
leftFooterText: 'Grid created with <a href="https://github.com/ghiscoding/slickgrid-universal" target="_blank">Slickgrid-Universal</a> <i class="mdi mdi-github"></i>',
},
enableTreeData: true, // you must enable this flag for the filtering & sorting to work as expected
treeDataOptions: {
Expand Down
35 changes: 20 additions & 15 deletions packages/common/src/services/__tests__/treeData.service.spec.ts
Expand Up @@ -32,6 +32,7 @@ const dataViewStub = {
endUpdate: jest.fn(),
getItem: jest.fn(),
getItemById: jest.fn(),
getItemCount: jest.fn(),
getItems: jest.fn(),
refresh: jest.fn(),
sort: jest.fn(),
Expand Down Expand Up @@ -321,11 +322,11 @@ describe('TreeData Service', () => {
beforeEach(() => {
jest.clearAllMocks();
mockFlatDataset = [
{ id: 0, file: 'TXT', size: 5.8, __hasChildren: true },
{ id: 1, file: 'myFile.txt', size: 0.5 },
{ id: 2, file: 'myMusic.txt', size: 5.3 },
{ id: 4, file: 'MP3', size: 3.4, __hasChildren: true },
{ id: 5, file: 'relaxation.mp3', size: 3.4 }
{ id: 0, file: 'TXT', size: 5.8, __hasChildren: true, __treeLevel: 0 },
{ id: 1, file: 'myFile.txt', size: 0.5, __treeLevel: 1 },
{ id: 2, file: 'myMusic.txt', size: 5.3, __treeLevel: 1 },
{ id: 4, file: 'MP3', size: 3.4, __hasChildren: true, __treeLevel: 0 },
{ id: 5, file: 'relaxation.mp3', size: 3.4, __treeLevel: 1 }
];
mockHierarchical = [
{ id: 0, file: 'TXT', files: [{ id: 1, file: 'myFile.txt', size: 0.5, }, { id: 2, file: 'myMusic.txt', size: 5.3, }] },
Expand All @@ -336,6 +337,7 @@ describe('TreeData Service', () => {

it('should collapse all items when calling the method with collapsing True', async () => {
const dataGetItemsSpy = jest.spyOn(dataViewStub, 'getItems').mockReturnValue(mockFlatDataset);
jest.spyOn(dataViewStub, 'getItemCount').mockReturnValue(mockFlatDataset.length);
jest.spyOn(SharedService.prototype, 'hierarchicalDataset', 'get').mockReturnValue(mockHierarchical);
const beginUpdateSpy = jest.spyOn(dataViewStub, 'beginUpdate');
const endUpdateSpy = jest.spyOn(dataViewStub, 'endUpdate');
Expand All @@ -349,12 +351,15 @@ describe('TreeData Service', () => {
expect(pubSubSpy).toHaveBeenCalledWith(`onTreeFullToggleEnd`, { type: 'full-collapse', previousFullToggleType: 'full-collapse', toggledItems: null, });
expect(dataGetItemsSpy).toHaveBeenCalled();
expect(beginUpdateSpy).toHaveBeenCalled();
expect(updateItemSpy).toHaveBeenNthCalledWith(1, 0, { __collapsed: true, __hasChildren: true, id: 0, file: 'TXT', size: 5.8 });
expect(updateItemSpy).toHaveBeenNthCalledWith(2, 4, { __collapsed: true, __hasChildren: true, id: 4, file: 'MP3', size: 3.4 });
expect(SharedService.prototype.hierarchicalDataset[0].file).toBe('TXT');
expect(updateItemSpy).toHaveBeenNthCalledWith(1, 0, { __collapsed: true, __hasChildren: true, id: 0, file: 'TXT', size: 5.8, __treeLevel: 0 });
expect(updateItemSpy).toHaveBeenNthCalledWith(2, 4, { __collapsed: true, __hasChildren: true, id: 4, file: 'MP3', size: 3.4, __treeLevel: 0 });
expect(SharedService.prototype.hierarchicalDataset[0].file).toBe('TXT')
expect(SharedService.prototype.hierarchicalDataset[0].__collapsed).toBeTrue();
expect(SharedService.prototype.hierarchicalDataset[1].file).toBe('MP3');
expect(SharedService.prototype.hierarchicalDataset[1].__collapsed).toBeTrue();
expect(service.getItemCount(0)).toBe(2); // get count by tree level 0
expect(service.getItemCount(1)).toBe(3);
expect(service.getItemCount()).toBe(5); // get full count of all tree
expect(endUpdateSpy).toHaveBeenCalled();
});

Expand All @@ -374,8 +379,8 @@ describe('TreeData Service', () => {
expect(dataGetItemsSpy).toHaveBeenCalled();
expect(dataGetItemsSpy).toHaveBeenCalled();
expect(beginUpdateSpy).toHaveBeenCalled();
expect(updateItemSpy).toHaveBeenNthCalledWith(1, 0, { customCollapsed: true, __hasChildren: true, id: 0, file: 'TXT', size: 5.8 });
expect(updateItemSpy).toHaveBeenNthCalledWith(2, 4, { customCollapsed: true, __hasChildren: true, id: 4, file: 'MP3', size: 3.4 });
expect(updateItemSpy).toHaveBeenNthCalledWith(1, 0, { customCollapsed: true, __hasChildren: true, id: 0, file: 'TXT', size: 5.8, __treeLevel: 0 });
expect(updateItemSpy).toHaveBeenNthCalledWith(2, 4, { customCollapsed: true, __hasChildren: true, id: 4, file: 'MP3', size: 3.4, __treeLevel: 0 });
expect(endUpdateSpy).toHaveBeenCalled();
});

Expand All @@ -393,8 +398,8 @@ describe('TreeData Service', () => {
expect(pubSubSpy).toHaveBeenCalledWith(`onTreeFullToggleEnd`, { type: 'full-expand', previousFullToggleType: 'full-expand', toggledItems: null, });
expect(dataGetItemsSpy).toHaveBeenCalled();
expect(beginUpdateSpy).toHaveBeenCalled();
expect(updateItemSpy).toHaveBeenNthCalledWith(1, 0, { __collapsed: false, __hasChildren: true, id: 0, file: 'TXT', size: 5.8 });
expect(updateItemSpy).toHaveBeenNthCalledWith(2, 4, { __collapsed: false, __hasChildren: true, id: 4, file: 'MP3', size: 3.4 });
expect(updateItemSpy).toHaveBeenNthCalledWith(1, 0, { __collapsed: false, __hasChildren: true, id: 0, file: 'TXT', size: 5.8, __treeLevel: 0 });
expect(updateItemSpy).toHaveBeenNthCalledWith(2, 4, { __collapsed: false, __hasChildren: true, id: 4, file: 'MP3', size: 3.4, __treeLevel: 0 });
expect(endUpdateSpy).toHaveBeenCalled();
});

Expand All @@ -413,7 +418,7 @@ describe('TreeData Service', () => {

expect(dataGetItemsSpy).toHaveBeenCalled();
expect(beginUpdateSpy).toHaveBeenCalled();
expect(updateItemSpy).toHaveBeenNthCalledWith(1, 4, { __collapsed: true, __hasChildren: true, id: 4, file: 'MP3', size: 3.4 });
expect(updateItemSpy).toHaveBeenNthCalledWith(1, 4, { __collapsed: true, __hasChildren: true, id: 4, file: 'MP3', size: 3.4, __treeLevel: 0 });
expect(pubSubSpy).not.toHaveBeenCalledWith(`onTreeItemToggled`);
expect(endUpdateSpy).toHaveBeenCalled();
});
Expand All @@ -432,7 +437,7 @@ describe('TreeData Service', () => {

expect(dataGetItemsSpy).not.toHaveBeenCalled();
expect(beginUpdateSpy).toHaveBeenCalled();
expect(updateItemSpy).toHaveBeenNthCalledWith(1, 4, { __collapsed: true, __hasChildren: true, id: 4, file: 'MP3', size: 3.4 });
expect(updateItemSpy).toHaveBeenNthCalledWith(1, 4, { __collapsed: true, __hasChildren: true, id: 4, file: 'MP3', size: 3.4, __treeLevel: 0 });
expect(pubSubSpy).toHaveBeenCalledWith(`onTreeItemToggled`, { fromItemId: 4, previousFullToggleType: 'full-collapse', toggledItems: [{ itemId: 4, isCollapsed: true }], type: 'toggle-collapse' });
expect(endUpdateSpy).toHaveBeenCalled();
});
Expand All @@ -452,7 +457,7 @@ describe('TreeData Service', () => {

expect(dataGetItemsSpy).toHaveBeenCalled();
expect(beginUpdateSpy).toHaveBeenCalled();
expect(updateItemSpy).toHaveBeenNthCalledWith(1, 4, { __collapsed: true, __hasChildren: true, id: 4, file: 'MP3', size: 3.4 });
expect(updateItemSpy).toHaveBeenNthCalledWith(1, 4, { __collapsed: true, __hasChildren: true, id: 4, file: 'MP3', size: 3.4, __treeLevel: 0 });
expect(pubSubSpy).toHaveBeenCalledWith(`onTreeItemToggled`, { fromItemId: 4, previousFullToggleType: 'full-collapse', toggledItems: [{ itemId: 4, isCollapsed: true }], type: 'toggle-collapse' });
expect(endUpdateSpy).toHaveBeenCalled();
});
Expand Down
14 changes: 14 additions & 0 deletions packages/common/src/services/treeData.service.ts
Expand Up @@ -190,6 +190,20 @@ export class TreeDataService {
};
}

/**
* Get the full item count of the Tree.
* When an optional tree level is provided, it will return the count for only that dedicated level (for example providing 0 would return the item count of all parent items)
* @param {Number} [treeLevel] - optional tree level to get item count from
* @returns
*/
getItemCount(treeLevel?: number) {
if (treeLevel !== undefined) {
const levelPropName = this.getTreeDataOptionPropName('levelPropName');
return this.dataView.getItems().filter(dataContext => dataContext[levelPropName] === treeLevel).length;
}
return this.dataView.getItemCount();
}

/**
* Get the current list of Tree Data item(s) that got toggled in the grid (basically the parents that the user clicked on the toggle icon to expand/collapse the child)
* @returns {Array<TreeToggledItem>} treeDataToggledItems - items that were toggled (array of `parentId` and `isCollapsed` flag)
Expand Down

0 comments on commit b3f8f94

Please sign in to comment.