diff --git a/docs/grid-functionalities/grouping-aggregators.md b/docs/grid-functionalities/grouping-aggregators.md
index ef73f6266..697317af5 100644
--- a/docs/grid-functionalities/grouping-aggregators.md
+++ b/docs/grid-functionalities/grouping-aggregators.md
@@ -2,6 +2,7 @@
- [Demo](#demo)
- [Description](#description)
- [Setup](#setup)
+- [Draggable Dropzone Location](#draggable-dropzone-location)
- [Aggregators](#aggregators)
- [SortComparers](https://github.com/ghiscoding/slickgrid-universal/blob/master/packages/common/src/sortComparers/sortComparers.index.ts)
- [GroupTotalsFormatter](#group-totals-formatter)
@@ -62,6 +63,43 @@ export class Example {
}
```
+### Draggable Dropzone Location
+
+The Draggable Grouping can be located in either the Top-Header or the Pre-Header as described below.
+
+#### Pre-Heaader
+Draggable Grouping can be located in either the Pre-Header of the Top-Header, however when it is located in the Pre-Header then the Header Grouping will not be available (because both of them would conflict with each other). Note that prior to the version 8.1 of Aurelia-Slickgrid, the Pre-Header was the default and only available option.
+
+```ts
+this.gridOptions = {
+ createPreHeaderPanel: true,
+ showPreHeaderPanel: true,
+ preHeaderPanelHeight: 26,
+ draggableGrouping: {
+ // ... any draggable plugin option
+ },
+}
+```
+
+#### Top-Heaader
+##### requires v8.1 and higher
+This is the preferred section since the Top-Header is on top of all headers (including pre-header) and it will always be the full grid width. Using the Top-Header also frees up the Pre-Header section for the potential use of Header Grouping.
+
+When using Draggable Grouping and Header Grouping together, you need to enable both top-header and pre-header.
+```ts
+this.gridOptions = {
+ // we'll use top-header for the Draggable Grouping
+ createTopHeaderPanel: true,
+ showTopHeaderPanel: true,
+ topHeaderPanelHeight: 35,
+
+ // pre-header will include our Header Grouping (i.e. "Common Factor")
+ createPreHeaderPanel: true,
+ showPreHeaderPanel: true,
+ preHeaderPanelHeight: 26,
+}
+```
+
### Aggregators
The `Aggregators` is basically the accumulator, the logic that will do the sum (or any other aggregate we defined). We simply need to instantiate the `Aggregator` by passing the column definition `field` that will be used to accumulate. For example, if we have a column definition of Cost and we want to calculate it's sum, we can call the `Aggregator` as follow
```ts
diff --git a/packages/aurelia-slickgrid/src/custom-elements/aurelia-slickgrid.ts b/packages/aurelia-slickgrid/src/custom-elements/aurelia-slickgrid.ts
index 1a717ec03..bc1a29869 100644
--- a/packages/aurelia-slickgrid/src/custom-elements/aurelia-slickgrid.ts
+++ b/packages/aurelia-slickgrid/src/custom-elements/aurelia-slickgrid.ts
@@ -673,7 +673,7 @@ export class AureliaSlickgridCustomElement {
if (gridOptions.enableTranslate) {
this.extensionService.translateAllExtensions(args.newLocale);
- if (gridOptions.createPreHeaderPanel && !gridOptions.enableDraggableGrouping) {
+ if ((gridOptions.createPreHeaderPanel && gridOptions.createTopHeaderPanel) || (gridOptions.createPreHeaderPanel && !gridOptions.enableDraggableGrouping)) {
this.groupingService.translateGroupingAndColSpan();
}
}
@@ -1358,7 +1358,10 @@ export class AureliaSlickgridCustomElement {
}
// when using Grouping/DraggableGrouping/Colspan register its Service
- if (this.gridOptions.createPreHeaderPanel && !this.gridOptions.enableDraggableGrouping && !this._registeredResources.some(r => r instanceof GroupingAndColspanService)) {
+ if (
+ ((this.gridOptions.createPreHeaderPanel && this.gridOptions.createTopHeaderPanel) || (this.gridOptions.createPreHeaderPanel && !this.gridOptions.enableDraggableGrouping))
+ && !this._registeredResources.some(r => r instanceof GroupingAndColspanService)
+ ) {
this._registeredResources.push(this.groupingService);
}
diff --git a/packages/demo/src/examples/slickgrid/example18.ts b/packages/demo/src/examples/slickgrid/example18.ts
index a814dcaa2..0443b6930 100644
--- a/packages/demo/src/examples/slickgrid/example18.ts
+++ b/packages/demo/src/examples/slickgrid/example18.ts
@@ -71,7 +71,7 @@ export class Example18 {
defineGrid() {
this.columnDefinitions = [
{
- id: 'title', name: 'Title', field: 'title',
+ id: 'title', name: 'Title', field: 'title', columnGroup: 'Common Factor',
width: 70, minWidth: 50,
cssClass: 'cell-title',
filterable: true,
@@ -87,7 +87,7 @@ export class Example18 {
}
},
{
- id: 'duration', name: 'Duration', field: 'duration',
+ id: 'duration', name: 'Duration', field: 'duration', columnGroup: 'Common Factor',
width: 70,
sortable: true,
filterable: true,
@@ -108,27 +108,8 @@ export class Example18 {
}
},
{
- id: 'percentComplete', name: '% Complete', field: 'percentComplete',
- minWidth: 70, width: 90,
- formatter: Formatters.percentCompleteBar,
- type: FieldType.number,
- filterable: true,
- filter: { model: Filters.compoundSlider },
- sortable: true,
- groupTotalsFormatter: GroupTotalFormatters.avgTotalsPercentage,
- grouping: {
- getter: 'percentComplete',
- formatter: (g) => `% Complete: ${g.value} (${g.count} items)`,
- aggregators: [
- new Aggregators.Sum('cost')
- ],
- aggregateCollapsed: false,
- collapsed: false
- },
- params: { groupFormatterPrefix: 'Avg: ' }
- },
- {
- id: 'start', name: 'Start', field: 'start', minWidth: 60,
+ id: 'start', name: 'Start', field: 'start', columnGroup: 'Period',
+ minWidth: 60,
sortable: true,
filterable: true,
filter: { model: Filters.compoundDate },
@@ -147,7 +128,7 @@ export class Example18 {
}
},
{
- id: 'finish', name: 'Finish', field: 'finish',
+ id: 'finish', name: 'Finish', field: 'finish', columnGroup: 'Period',
minWidth: 60,
sortable: true,
filterable: true,
@@ -167,7 +148,7 @@ export class Example18 {
}
},
{
- id: 'cost', name: 'Cost', field: 'cost',
+ id: 'cost', name: 'Cost', field: 'cost', columnGroup: 'Analysis',
width: 90,
sortable: true,
filterable: true,
@@ -187,7 +168,27 @@ export class Example18 {
}
},
{
- id: 'effortDriven', name: 'Effort-Driven', field: 'effortDriven',
+ id: 'percentComplete', name: '% Complete', field: 'percentComplete', columnGroup: 'Analysis',
+ minWidth: 70, width: 90,
+ formatter: Formatters.percentCompleteBar,
+ type: FieldType.number,
+ filterable: true,
+ filter: { model: Filters.compoundSlider },
+ sortable: true,
+ groupTotalsFormatter: GroupTotalFormatters.avgTotalsPercentage,
+ grouping: {
+ getter: 'percentComplete',
+ formatter: (g) => `% Complete: ${g.value} (${g.count} items)`,
+ aggregators: [
+ new Aggregators.Sum('cost')
+ ],
+ aggregateCollapsed: false,
+ collapsed: false
+ },
+ params: { groupFormatterPrefix: 'Avg: ' }
+ },
+ {
+ id: 'effortDriven', name: 'Effort-Driven', field: 'effortDriven', columnGroup: 'Analysis',
width: 80, minWidth: 20, maxWidth: 100,
cssClass: 'cell-effort-driven',
sortable: true,
@@ -214,9 +215,18 @@ export class Example18 {
rightPadding: 10
},
enableDraggableGrouping: true,
+
+ // pre-header will include our Header Grouping (i.e. "Common Factor")
+ // Draggable Grouping could be located in either the Pre-Header OR the new Top-Header
createPreHeaderPanel: true,
showPreHeaderPanel: true,
- preHeaderPanelHeight: 40,
+ preHeaderPanelHeight: 30,
+
+ // when Top-Header is created, it will be used by the Draggable Grouping (otherwise the Pre-Header will be used)
+ createTopHeaderPanel: true,
+ showTopHeaderPanel: true,
+ topHeaderPanelHeight: 35,
+
showCustomFooter: true,
enableFiltering: true,
// you could debounce/throttle the input text filter if you have lots of data
@@ -234,7 +244,9 @@ export class Example18 {
draggableGrouping: {
dropPlaceHolderText: 'Drop a column header here to group by the column',
// groupIconCssClass: 'mdi mdi-drag-vertical',
- deleteIconCssClass: 'mdi mdi-close',
+ deleteIconCssClass: 'mdi mdi-close text-color-danger',
+ sortAscIconCssClass: 'mdi mdi-arrow-up',
+ sortDescIconCssClass: 'mdi mdi-arrow-down',
onGroupChanged: (_e, args) => this.onGroupChanged(args),
onExtensionRegistered: (extension) => this.draggableGroupingPlugin = extension,
},
diff --git a/test/cypress/e2e/example18.cy.ts b/test/cypress/e2e/example18.cy.ts
index 9005fb026..7e04e586d 100644
--- a/test/cypress/e2e/example18.cy.ts
+++ b/test/cypress/e2e/example18.cy.ts
@@ -1,5 +1,6 @@
describe('Example 18 - Draggable Grouping & Aggregators', () => {
- const fullTitles = ['Title', 'Duration', '% Complete', 'Start', 'Finish', 'Cost', 'Effort-Driven'];
+ const preHeaders = ['Common Factor', 'Period', 'Analysis', ''];
+ const fullTitles = ['Title', 'Duration', 'Start', 'Finish', 'Cost', '% Complete', 'Effort-Driven'];
const GRID_ROW_HEIGHT = 35;
it('should display Example title', () => {
@@ -7,13 +8,26 @@ describe('Example 18 - Draggable Grouping & Aggregators', () => {
cy.get('h2').should('contain', 'Example 18: Draggable Grouping & Aggregators');
});
- it('should have exact column titles on 1st grid', () => {
+ it('should have exact column (pre-header) grouping titles in grid', () => {
cy.get('#grid18')
- .find('.slick-header-columns')
+ .find('.slick-preheader-panel .slick-header-columns')
+ .children()
+ .each(($child, index) => expect($child.text()).to.eq(preHeaders[index]));
+ });
+
+ it('should have exact column titles in grid', () => {
+ cy.get('#grid18')
+ .find('.slick-header:not(.slick-preheader-panel) .slick-header-columns')
.children()
.each(($child, index) => expect($child.text()).to.eq(fullTitles[index]));
});
+ it('should have a draggable dropzone on top of the grid in the top-header section', () => {
+ cy.get('#grid18')
+ .find('.slick-topheader-panel .slick-dropzone:visible')
+ .contains('Drop a column header here to group by the column');
+ });
+
describe('Grouping Tests', () => {
it('should "Group by Duration & sort groups by value" then Collapse All and expect only group titles', () => {
cy.get('[data-test="add-50k-rows-btn"]').click();
@@ -141,8 +155,8 @@ describe('Example 18 - Draggable Grouping & Aggregators', () => {
.should('exist');
});
- it('should use the preheader Toggle All button and expect all groups to now be expanded', () => {
- cy.get('.slick-preheader-panel .slick-group-toggle-all').click();
+ it('should use the topheader Toggle All button and expect all groups to now be expanded', () => {
+ cy.get('.slick-topheader-panel .slick-group-toggle-all').click();
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(0) .slick-group-toggle.expanded`).should('have.length', 1);
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(0) .slick-group-title`).should('contain', 'Effort-Driven: False');
@@ -153,8 +167,8 @@ describe('Example 18 - Draggable Grouping & Aggregators', () => {
.should('have.css', 'marginLeft').and('eq', `15px`);
});
- it('should use the preheader Toggle All button again and expect all groups to now be collapsed', () => {
- cy.get('.slick-preheader-panel .slick-group-toggle-all').click();
+ it('should use the topheader Toggle All button again and expect all groups to now be collapsed', () => {
+ cy.get('.slick-topheader-panel .slick-group-toggle-all').click();
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(0) .slick-group-toggle.collapsed`).should('have.length', 1);
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(0) .slick-group-title`).should('contain', 'Effort-Driven: False');