Skip to content

Commit

Permalink
feat(tree): add dynamicallyToggledItemState method to toggle parent(s)
Browse files Browse the repository at this point in the history
  • Loading branch information
ghiscoding committed Aug 12, 2021
1 parent f485727 commit 26369f9
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 1 deletion.
Expand Up @@ -31,6 +31,10 @@ <h6 class="title is-6 italic">
<span class="icon mdi mdi-arrow-collapse"></span>
<span>Collapse All (without triggering event)</span>
</button>
<button onclick.delegate="dynamicallyToggledFirstParent()" data-test="dynamically-toggle-first-parent-btn"
class="button is-small">
<span>Dynamically Toggle First Parent</span>
</button>
<button onclick.delegate="reapplyToggledItems()" data-test="reapply-toggled-items-btn" class="button is-small"
disabled.bind="hasNoExpandCollapseChanged">
<span class="icon mdi mdi-history"></span>
Expand Down
14 changes: 14 additions & 0 deletions examples/webpack-demo-vanilla-bundle/src/examples/example05.ts
Expand Up @@ -305,6 +305,20 @@ export class Example5 {
console.log(this.sgb.treeDataService.getToggledItems());
}

dynamicallyToggledFirstParent() {
const parentPropName = 'parentId';
const treeLevelPropName = 'treeLevel'; // if undefined in your options, the default prop name is "__treeLevel"
const newTreeLevel = 1;

// find first parent object and toggle it
const childItemFound = this.sgb.dataset.find((item) => item[treeLevelPropName] === newTreeLevel);
const parentItemFound = this.sgb.dataView.getItemByIdx(childItemFound[parentPropName]);

if (childItemFound && parentItemFound) {
this.sgb.treeDataService.dynamicallyToggleItemState([{ itemId: parentItemFound.id, isCollapsed: !parentItemFound.__collapsed }]);
}
}

reapplyToggledItems() {
this.sgb.treeDataService.applyToggledItemStateChanges(this.treeToggleItems);
}
Expand Down
20 changes: 20 additions & 0 deletions packages/common/src/services/__tests__/treeData.service.spec.ts
Expand Up @@ -462,6 +462,26 @@ describe('TreeData Service', () => {
expect(endUpdateSpy).toHaveBeenCalled();
});
});

describe('dynamicallyToggleItemState method', () => {
it('should execute the method and also trigger an event by default', () => {
jest.spyOn(dataViewStub, 'getItemById').mockReturnValue(mockFlatDataset[3]);
jest.spyOn(SharedService.prototype, 'hierarchicalDataset', 'get').mockReturnValue(mockHierarchical);
const beginUpdateSpy = jest.spyOn(dataViewStub, 'beginUpdate');
const endUpdateSpy = jest.spyOn(dataViewStub, 'endUpdate');
const updateItemSpy = jest.spyOn(dataViewStub, 'updateItem');
const pubSubSpy = jest.spyOn(pubSubServiceStub, 'publish');

service.init(gridStub);
service.dynamicallyToggleItemState([{ itemId: 4, isCollapsed: true }], true);
service.dynamicallyToggleItemState([{ itemId: 4, isCollapsed: true }], true); // calling twice shouldn't change toggledItems array

expect(beginUpdateSpy).toHaveBeenCalled();
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-expand', toggledItems: [{ itemId: 4, isCollapsed: true }], type: 'toggle-collapse' });
expect(endUpdateSpy).toHaveBeenCalled();
});
});
});

describe('convertFlatParentChildToTreeDatasetAndSort method', () => {
Expand Down
22 changes: 21 additions & 1 deletion packages/common/src/services/treeData.service.ts
Expand Up @@ -107,7 +107,7 @@ export class TreeDataService {
}

/**
* Apply different tree toggle state changes by providing an array of parentIds that are designated as collapsed (or not).
* Apply different tree toggle state changes (to ALL rows, the entire dataset) by providing an array of parentIds that are designated as collapsed (or not).
* User will have to provide an array of `parentId` and `isCollapsed` boolean and the code will only apply the ones that are tagged as collapsed, everything else will be expanded
* @param {Array<TreeToggledItem>} treeToggledItems - array of parentId which are tagged as changed
* @param {ToggleStateChangeType} previousFullToggleType - optionally provide the previous full toggle type ('full-expand' or 'full-collapse')
Expand Down Expand Up @@ -142,6 +142,26 @@ export class TreeDataService {
});
}

// then we reapply only the ones that changed (provided as argument to the function)
// we also don't need to call the DataView `endUpdate()`, for the transaction ending, because it will be called inside this other method
this.dynamicallyToggleItemState(treeToggledItems, shouldTriggerEvent);
}
}

/**
* Dynamically toggle and change state of certain parent items by providing an array of parentIds that are designated as to be collapsed (or not).
* User will have to provide an array of `parentId` and `isCollapsed` boolean, only the provided list of items will be toggled and nothing else.
*
* NOTE: the `applyToggledItemStateChanges()` method is very similar but on top of toggling the `treeToggledItems` it WILL ALSO collapse everything else.
* @param {Array<TreeToggledItem>} treeToggledItems - array of parentId which are tagged as changed
* @param {Boolean} shouldTriggerEvent - should we trigger a toggled item event? defaults to True
*/
dynamicallyToggleItemState(treeToggledItems: TreeToggledItem[], shouldTriggerEvent = true) {
if (Array.isArray(treeToggledItems)) {
// for the rows we identified as collapsed, we'll send them to the DataView with the new updated collapsed flag
// and we'll refresh the DataView to see the collapsing applied in the grid
this.dataView.beginUpdate(true);

// then we reapply only the ones that changed (provided as argument to the function)
for (const collapsedItem of treeToggledItems) {
const item = this.dataView.getItemById(collapsedItem.itemId);
Expand Down
Binary file not shown.
8 changes: 8 additions & 0 deletions test/cypress/integration/example05.spec.js
Expand Up @@ -301,4 +301,12 @@ describe('Example 05 - Tree Data (from a flat dataset with parentId references)'

cy.get(`.grid5 .slick-group-toggle.expanded`).should('have.length', 2);
});

it('should be able to click on "Dynamically Toggle First Parent" expect only the first parent item to get collapsed', () => {
cy.get('[data-test=dynamically-toggle-first-parent-btn]')
.contains('Dynamically Toggle First Parent')
.click();

cy.get(`.grid5 .slick-group-toggle.expanded`).should('have.length', 0);
});
});

0 comments on commit 26369f9

Please sign in to comment.