Skip to content

Commit

Permalink
feat(grid): add sample for Header Grouping spanning accros multiple c…
Browse files Browse the repository at this point in the history
…ols (#43)

* feat(grid): start working on Header Group spanning

* feat(event): add asg:onBeforeResize event on the resizer service

* feat(grid): add sample for Header Grouping spanning accros multiple cols

* fix(grid): disable resize since it isn't working good with header group

* fix(grid): make grid size fit in the window
  • Loading branch information
ghiscoding authored Apr 10, 2018
1 parent 7d194ed commit 67ff867
Show file tree
Hide file tree
Showing 10 changed files with 179 additions and 29 deletions.
27 changes: 25 additions & 2 deletions aurelia-slickgrid/src/aurelia-slickgrid/aurelia-slickgrid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import {
GridEventService,
GridExtraService,
GridStateService,
GroupingAndColspanService,
ResizerService,
SortService,
toKebabCase
Expand All @@ -57,7 +58,22 @@ const aureliaEventPrefix = 'asg';
const eventPrefix = 'sg';

// Aurelia doesn't support well TypeScript @autoinject in a Plugin so we'll do it the old fashion way
@inject(ControlAndPluginService, ExportService, Element, EventAggregator, FilterService, GraphqlService, GridEventService, GridExtraService, GridStateService, I18N, ResizerService, SortService, Container)
@inject(
ControlAndPluginService,
ExportService,
Element,
EventAggregator,
FilterService,
GraphqlService,
GridEventService,
GridExtraService,
GridStateService,
GroupingAndColspanService,
I18N,
ResizerService,
SortService,
Container
)
export class AureliaSlickgridCustomElement {
private _dataset: any[];
private _eventHandler: any = new Slick.EventHandler();
Expand Down Expand Up @@ -88,6 +104,7 @@ export class AureliaSlickgridCustomElement {
private gridEventService: GridEventService,
private gridExtraService: GridExtraService,
private gridStateService: GridStateService,
private groupingAndColspanService: GroupingAndColspanService,
private i18n: I18N,
private resizer: ResizerService,
private sortService: SortService,
Expand Down Expand Up @@ -140,6 +157,11 @@ export class AureliaSlickgridCustomElement {
// attach resize ONLY after the dataView is ready
this.attachResizeHook(this.grid, this.gridOptions);

// attach grouping and header grouping colspan service
if (this.gridOptions.createPreHeaderPanel) {
this.groupingAndColspanService.init(this.grid, this.dataview);
}

// attach grid extra service
this.gridExtraService.init(this.grid, this.columnDefinitions, this.gridOptions, this.dataview);

Expand Down Expand Up @@ -174,6 +196,7 @@ export class AureliaSlickgridCustomElement {
this.filterService.dispose();
this.gridEventService.dispose();
this.gridStateService.dispose();
this.groupingAndColspanService.dispose();
this.resizer.dispose();
this.sortService.dispose();
this.grid.destroy();
Expand Down Expand Up @@ -392,7 +415,7 @@ export class AureliaSlickgridCustomElement {
}

// auto-resize grid on browser resize
this.resizer.init(grid, options);
this.resizer.init(grid);
if (grid && options.enableAutoResize) {
this.resizer.attachAutoResizeDataGrid();
if (options.autoFitColumnsOnFirstLoad && typeof grid.autosizeColumns === 'function') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ export interface Column {
/** Block event triggering of an insert? */
cannotTriggerInsert?: boolean;

/** CSS class to add to the column cell */
cssClass?: string;
/** Column group name for grouping of column headers spanning accross multiple columns */
columnGroup?: string;

/** Column span in pixels or `*`, only input the number value */
colspan?: number | '*';

/** CSS class to add to the column cell */
cssClass?: string;

/** Do we want default sort to be ascending? True by default */
defaultSortAsc?: boolean;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ export interface GridOption {
/** Checkbox Select Plugin options (columnTitle, forceFitTitle, syncResizeTitle) */
columnPicker?: ColumnPicker;

/** Default to false, which leads to create an extra pre-header panel (on top of column header) for column grouping purposes */
createPreHeaderPanel?: boolean;

/** Defaults to false, which leads to create the footer row of the grid */
createFooterRow?: boolean;

Expand Down Expand Up @@ -245,6 +248,9 @@ export interface GridOption {
/** "params" is a generic property and can be used to pass custom paramaters to your Formatter/Editor or anything else */
params?: any | any[];

/** Extra pre-header panel height (on top of column header) */
preHeaderPanelHeight?: number;

/** Do we want to preserve copied selection on paste? */
preserveCopiedSelectionOnPaste?: boolean;

Expand Down Expand Up @@ -275,6 +281,9 @@ export interface GridOption {
/** Do we want to show header row? */
showHeaderRow?: boolean;

/** Do we want to show the extra pre-header panel (on top of column header) for column grouping purposes */
showPreHeaderPanel?: boolean;

/** Do we want to show top panel row? */
showTopPanel?: boolean;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { EventAggregator, Subscription } from 'aurelia-event-aggregator';
import { inject } from 'aurelia-framework';
import {
Column,
GridOption
} from './../models/index';
import * as $ from 'jquery';

// using external non-typed js libraries
declare var Slick: any;

@inject(EventAggregator)
export class GroupingAndColspanService {
private _eventHandler = new Slick.EventHandler();
private _dataView: any;
private _grid: any;
private _gridOptions: GridOption;
private _columnDefinitions: Column[];
aureliaEventPrefix: string;

constructor(private ea: EventAggregator) { }

init(grid: any, dataView: any) {
this._grid = grid;
this._dataView = dataView;
if (grid) {
this._gridOptions = grid.getOptions();
this._columnDefinitions = grid.getColumns();
}

this.aureliaEventPrefix = (this._gridOptions && this._gridOptions.defaultAureliaEventPrefix) ? this._gridOptions.defaultAureliaEventPrefix : 'asg';

// When dealing with Pre-Header Grouping colspan, we need to re-create the pre-header in multiple occasions
// for all these occasions, we have to trigger a re-create
if (this._gridOptions.createPreHeaderPanel) {
this._eventHandler.subscribe(grid.onSort, (e: Event, args: any) => {
this.createPreHeaderRowGroupingTitle();
});
this._eventHandler.subscribe(grid.onColumnsResized, (e: Event, args: any) => {
this.createPreHeaderRowGroupingTitle();
});
this._eventHandler.subscribe(dataView.onRowCountChanged, (e: Event, args: any) => {
this.createPreHeaderRowGroupingTitle();
});

// also not sure why at this point, but it seems that I need to call the 1st create in a delayed execution
// probably some kind of timing issues and delaying it until the grid is fully ready does help
setTimeout(() => {
this.createPreHeaderRowGroupingTitle();
}, 50);
}
}

dispose() {
// unsubscribe all SlickGrid events
this._eventHandler.unsubscribeAll();
}

createPreHeaderRowGroupingTitle() {
const $preHeaderPanel = $(this._grid.getPreHeaderPanel())
.empty()
.addClass('slick-header-columns')
.css('left', '-1000px')
.width(this._grid.getHeadersWidth());
$preHeaderPanel.parent().addClass('slick-header');
const headerColumnWidthDiff = this._grid.getHeaderColumnWidthDiff();
let m;
let header;
let lastColumnGroup = '';
let widthTotal = 0;

for (let i = 0; i < this._columnDefinitions.length; i++) {
m = this._columnDefinitions[i];
if (lastColumnGroup === m.columnGroup && i > 0) {
widthTotal += m.width;
header.width(widthTotal - headerColumnWidthDiff);
} else {
widthTotal = m.width;
header = $(`<div class="ui-state-default slick-header-column" />`)
.html(`<span class="slick-column-name">${m.columnGroup || ''}</span>`)
.width(m.width - headerColumnWidthDiff)
.appendTo($preHeaderPanel);
}
lastColumnGroup = m.columnGroup;
}
}
}
1 change: 1 addition & 0 deletions aurelia-slickgrid/src/aurelia-slickgrid/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export * from './gridExtra.service';
export * from './gridExtraUtils';
export * from './gridState.service';
export * from './grid-odata.service';
export * from './groupingAndColspan.service';
export * from './odata.service';
export * from './resizer.service';
export * from './sort.service';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { inject } from 'aurelia-framework';
import { GridOption } from './../models/index';
import * as $ from 'jquery';
import { EventAggregator } from 'aurelia-event-aggregator';

// global constants, height/width are in pixels
const DATAGRID_MIN_HEIGHT = 180;
Expand All @@ -15,14 +16,21 @@ export interface GridDimension {
heightWithPagination?: number;
}

@inject(EventAggregator)
export class ResizerService {
private _grid: any;
private _gridOptions: GridOption;
private _lastDimensions: GridDimension;
aureliaEventPrefix: string;

init(grid: any, gridOptions: GridOption): void {
constructor(private ea: EventAggregator) { }

init(grid: any): void {
this._grid = grid;
this._gridOptions = gridOptions;
if (grid) {
this._gridOptions = grid.getOptions();
}
this.aureliaEventPrefix = (this._gridOptions && this._gridOptions.defaultAureliaEventPrefix) ? this._gridOptions.defaultAureliaEventPrefix : 'asg';
}

/**
Expand All @@ -42,6 +50,7 @@ export class ResizerService {
// -- 2nd attach a trigger on the Window DOM element, so that it happens also when resizing after first load
// -- attach auto-resize to Window object only if it exist
$(window).on('resize.grid', () => {
this.ea.publish(`${this.aureliaEventPrefix}:onBeforeResize`, true);
// for some yet unknown reason, calling the resize twice removes any stuttering/flickering when changing the height and makes it much smoother
this.resizeGrid();
this.resizeGrid();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ $row-selected-color: #e2e2c5 !default;
$row-checkbox-selector-background: inherit !default;
$row-checkbox-selector-border: none !default;

/* Pre-Header - Header Grouping colspan */
$preheader-border-left: 1px solid #c0c0c0 !default;
$preheader-border-right: none !default;
$preheader-border-bottom: none !default;
$preheader-border-top: none !default;
$preheader-font-size: $font-size-base + 2px !default;

/* header */
$header-padding-top: 4px !default;
$header-padding-right: 4px !default;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,13 @@
}
}

.slick-preheader-panel.ui-state-default {
.slick-header-column {
border-left: $preheader-border-left !important;
font-size: $preheader-font-size !important;
}
}


/*
.slick-header-columns:last-child .slick-header-column:last-child {
Expand Down
2 changes: 1 addition & 1 deletion aurelia-slickgrid/src/examples/slickgrid/example14.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ <h2>${title}</h2>
<div class="subtitle" innerhtml.bind="subTitle"></div>

<aurelia-slickgrid grid-id="grid1" column-definitions.bind="columnDefinitions" grid-options.bind="gridOptions" dataset.bind="dataset"
sg-on-dataview-created.delegate="onDataviewCreated($event.detail)">
sg-on-dataview-created.delegate="onDataviewCreated($event.detail)" grid-height="500" grid-width="800">
</aurelia-slickgrid>
</template>
48 changes: 26 additions & 22 deletions aurelia-slickgrid/src/examples/slickgrid/example14.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@ import * as $ from 'jquery';

@autoinject()
export class Example14 {
title = 'Example 14: Column Span';
title = 'Example 14: Column Span & Header Grouping';
subTitle = `
This example demonstrates how to easily span a column over multiple columns.
<ul>
<li>However please note that for this to work properly, you need to call the "dataView.getItemMetadata"
<b>only</b> after the "dataView" is created for it to render at the correct time (else you will face timing UI issues)
</li>
<li>Note that you can add Sort but remember that it will sort by the data that the row contains, even if the data is visually hidden by colspan it will still sort it</li>
<li>
Header Grouping spanning accross multiple columns is working but has some UI issues on window resize.
If anyone can fix it, probably some CSS issues, please let us know.
</li>
</ul>
`;
columnDefinitions: Column[];
Expand All @@ -26,23 +30,23 @@ export class Example14 {

defineGrid() {
this.columnDefinitions = [
{ id: 'title', name: 'Title', field: 'title', sortable: true },
{ id: 'duration', name: 'Duration', field: 'duration' },
{ id: '%', name: '% Complete', field: 'percentComplete', selectable: false },
{ id: 'start', name: 'Start', field: 'start' },
{ id: 'finish', name: 'Finish', field: 'finish' },
{ id: 'effort-driven', name: 'Effort Driven', field: 'effortDriven', type: FieldType.boolean }
{ id: 'title', name: 'Title', field: 'title', sortable: true, columnGroup: 'Common Factor' },
{ id: 'duration', name: 'Duration', field: 'duration', columnGroup: 'Common Factor' },
{ id: 'start', name: 'Start', field: 'start', columnGroup: 'Period' },
{ id: 'finish', name: 'Finish', field: 'finish', columnGroup: 'Period' },
{ id: '%', name: '% Complete', field: 'percentComplete', selectable: false, columnGroup: 'Analysis' },
{ id: 'effort-driven', name: 'Effort Driven', field: 'effortDriven', type: FieldType.boolean, columnGroup: 'Analysis' }
];

this.gridOptions = {
enableAutoResize: true,
autoResize: {
containerId: 'demo-container',
sidePadding: 15
},
enableAutoResize: false,
enableCellNavigation: true,
enableColumnReorder: false,
enableSorting: true
enableSorting: true,
createPreHeaderPanel: true,
showPreHeaderPanel: true,
preHeaderPanelHeight: 25,
explicitInitialization: true
};
}

Expand All @@ -62,6 +66,15 @@ export class Example14 {
}
}

/** Execute after DataView is created and ready */
onDataviewCreated(dataView) {
// populate the dataset once the DataView is ready
this.getData();

// render different colspan right after the DataView is filled
this.renderDifferentColspan(dataView);
}

/** Call the "getItemMetadata" on the DataView to render different column span */
renderDifferentColspan(dataView: any) {
dataView.getItemMetadata = (rowNumber: number) => {
Expand All @@ -86,13 +99,4 @@ export class Example14 {
}
};
}

/** Execute after DataView is created and ready */
onDataviewCreated(dataView) {
// populate the dataset once the DataView is ready
this.getData();

// render different colspan right after the DataView is filled
this.renderDifferentColspan(dataView);
}
}

0 comments on commit 67ff867

Please sign in to comment.