Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sort): add a Clear Sorting function and grid menu command #39

Merged
merged 1 commit into from
Apr 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions aurelia-slickgrid/assets/i18n/en/aurelia-slickgrid.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"ALL_SELECTED": "All Selected",
"CLEAR_ALL_FILTERS": "Clear All Filters",
"CLEAR_ALL_SORTING": "Clear All Sorting",
"COLUMNS": "Columns",
"COMMANDS": "Commands",
"CONTAINS": "Contains",
Expand Down
1 change: 1 addition & 0 deletions aurelia-slickgrid/assets/i18n/fr/aurelia-slickgrid.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"ALL_SELECTED": "Tout sélectionnés",
"CLEAR_ALL_FILTERS": "Effacer tous les filtres",
"CLEAR_ALL_SORTING": "Effacer tous les tris",
"COLUMNS": "Colonnes",
"COMMANDS": "Commandes",
"CONTAINS": "Contient",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ export class AureliaSlickgridCustomElement {

// attach external sorting (backend) when available or default onSort (dataView)
if (gridOptions.enableSorting) {
(gridOptions.backendServiceApi || gridOptions.onBackendEventApi) ? this.sortService.attachBackendOnSort(grid, gridOptions) : this.sortService.attachLocalOnSort(grid, gridOptions, this.dataview, this.columnDefinitions);
(gridOptions.backendServiceApi || gridOptions.onBackendEventApi) ? this.sortService.attachBackendOnSort(grid, dataView) : this.sortService.attachLocalOnSort(grid, dataView);
}

// attach external filter (backend) when available or default onFilter (dataView)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,16 @@ export const GlobalGridOptions: GridOption = {
hideForceFitButton: false,
hideSyncResizeButton: true,
iconCssClass: 'fa fa-bars',
iconClearAllFiltersCommand: 'fa fa-filter text-danger',
iconClearAllSortingCommand: 'fa fa-unsorted text-danger',
iconExportCsvCommand: 'fa fa-download',
iconExportTextDelimitedCommand: 'fa fa-download',
iconRefreshDatasetCommand: 'fa fa-refresh',
iconToggleFilterCommand: 'fa fa-random',
menuWidth: 16,
resizeOnShowHeaderRow: false,
showClearAllFiltersCommand: true,
showClearAllSortingCommand: true,
showExportCsvCommand: true,
showRefreshDatasetCommand: true,
showToggleFilterCommand: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,5 @@ export interface BackendService {
onPaginationChanged: (event: Event | undefined, args: PaginationChangedArgs) => string;

/** Execute when any of the sorters changed */
onSortChanged: (event: Event, args: SortChangedArgs) => string;
onSortChanged: (event: Event | null, args: SortChangedArgs) => string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,12 @@ export interface GridMenu {
/** Defaults to False, which will resize the Header Row and remove the width of the Grid Menu icon from it's total width. */
resizeOnShowHeaderRow?: boolean;

/** Defaults to True, which will show the "Clear All Filter" command in the Grid Menu (Grid Option "enableFiltering: true" has to be enabled) */
/** Defaults to True, which will show the "Clear All Filters" command in the Grid Menu (Grid Option "enableFiltering: true" has to be enabled) */
showClearAllFiltersCommand?: boolean;

/** Defaults to True, which will show the "Clear All Sorting" command in the Grid Menu (Grid Option "enableSorting: true" has to be enabled) */
showClearAllSortingCommand?: boolean;

/** Defaults to True, which will show the "Export to CSV" command in the Grid Menu (Grid Option "enableExport: true" has to be enabled) */
showExportCsvCommand?: boolean;

Expand All @@ -49,6 +52,24 @@ export interface GridMenu {
/** Defaults to True, which will show the "Toggle Filter Row" command in the Grid Menu (Grid Option "enableFiltering: true" has to be enabled) */
showToggleFilterCommand?: boolean;

/** icon for the "Clear All Filters" command */
iconClearAllFiltersCommand?: string;

/** icon for the "Clear All Sorting" command */
iconClearAllSortingCommand?: string;

/** icon for the "Export to CSV" command */
iconExportCsvCommand?: string;

/** icon for the "Export to Text Delimited" command */
iconExportTextDelimitedCommand?: string;

/** icon for the "Refresh Dataset" command */
iconRefreshDatasetCommand?: string;

/** icon for the "Toggle Filter Row" command */
iconToggleFilterCommand?: string;

/** Defaults to "Synchronous resize" which is 1 of the last 2 checkbox title shown at the end of the picker list */
syncResizeTitle?: string;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { inject } from 'aurelia-framework';
import { I18N } from 'aurelia-i18n';
import { ExportService } from './export.service';
import { FilterService } from './filter.service';
import {
CellArgs,
CustomGridMenu,
Expand All @@ -15,12 +13,15 @@ import {
HeaderMenuOnBeforeMenuShowArgs,
FileType
} from './../models/index';
import { ExportService } from './export.service';
import { FilterService } from './filter.service';
import { SortService } from './sort.service';
import * as $ from 'jquery';

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

@inject(ExportService, FilterService, I18N)
@inject(ExportService, FilterService, I18N, SortService)
export class ControlAndPluginService {
private _dataView: any;
private _grid: any;
Expand All @@ -37,7 +38,12 @@ export class ControlAndPluginService {
gridMenuControl: any;
rowSelectionPlugin: any;

constructor(private exportService: ExportService, private filterService: FilterService, private i18n: I18N) { }
constructor(
private exportService: ExportService,
private filterService: FilterService,
private i18n: I18N,
private sortService: SortService
) { }

/**
* Attach/Create different Controls or Plugins after the Grid is created
Expand Down Expand Up @@ -246,7 +252,7 @@ export class ControlAndPluginService {
if (options && options.gridMenu && options.gridMenu.showClearAllFiltersCommand && options.gridMenu.customItems && options.gridMenu.customItems.filter((item: CustomGridMenu) => item.command === 'clear-filter').length === 0) {
options.gridMenu.customItems.push(
{
iconCssClass: 'fa fa-filter text-danger',
iconCssClass: options.gridMenu.iconClearAllFiltersCommand || 'fa fa-filter text-danger',
title: options.enableTranslate ? this.i18n.tr('CLEAR_ALL_FILTERS') : 'Clear All Filters',
disabled: false,
command: 'clear-filter',
Expand All @@ -258,11 +264,11 @@ export class ControlAndPluginService {
if (options && options.gridMenu && options.gridMenu.showToggleFilterCommand && options.gridMenu.customItems && options.gridMenu.customItems.filter((item: CustomGridMenu) => item.command === 'toggle-filter').length === 0) {
options.gridMenu.customItems.push(
{
iconCssClass: 'fa fa-random',
iconCssClass: options.gridMenu.iconToggleFilterCommand || 'fa fa-random',
title: options.enableTranslate ? this.i18n.tr('TOGGLE_FILTER_ROW') : 'Toggle Filter Row',
disabled: false,
command: 'toggle-filter',
positionOrder: 51
positionOrder: 52
}
);
}
Expand All @@ -271,38 +277,52 @@ export class ControlAndPluginService {
if (options && options.gridMenu && options.gridMenu.showRefreshDatasetCommand && backendApi && options.gridMenu.customItems && options.gridMenu.customItems.filter((item: CustomGridMenu) => item.command === 'refresh-dataset').length === 0) {
options.gridMenu.customItems.push(
{
iconCssClass: 'fa fa-refresh',
iconCssClass: options.gridMenu.iconRefreshDatasetCommand || 'fa fa-refresh',
title: options.enableTranslate ? this.i18n.tr('REFRESH_DATASET') : 'Refresh Dataset',
disabled: false,
command: 'refresh-dataset',
positionOrder: 54
}
);
}
}

if (options.enableSorting) {
// show grid menu: clear all sorting
if (options && options.gridMenu && options.gridMenu.showClearAllSortingCommand && options.gridMenu.customItems && options.gridMenu.customItems.filter((item: CustomGridMenu) => item.command === 'clear-sorting').length === 0) {
options.gridMenu.customItems.push(
{
iconCssClass: options.gridMenu.iconClearAllSortingCommand || 'fa fa-unsorted text-danger',
title: options.enableTranslate ? this.i18n.tr('CLEAR_ALL_SORTING') : 'Clear All Sorting',
disabled: false,
command: 'clear-sorting',
positionOrder: 51
}
);
}
}

// show grid menu: export to file
if (options && options.enableExport && options.gridMenu && options.gridMenu.showExportCsvCommand && options.gridMenu.customItems && options.gridMenu.customItems.filter((item: CustomGridMenu) => item.command === 'export-csv').length === 0) {
options.gridMenu.customItems.push(
{
iconCssClass: 'fa fa-download',
iconCssClass: options.gridMenu.iconExportCsvCommand || 'fa fa-download',
title: options.enableTranslate ? this.i18n.tr('EXPORT_TO_CSV') : 'Export in CSV format',
disabled: false,
command: 'export-csv',
positionOrder: 52
positionOrder: 53
}
);
}
// show grid menu: export to text file as tab delimited
if (options && options.enableExport && options.gridMenu && options.gridMenu.showExportTextDelimitedCommand && options.gridMenu.customItems && options.gridMenu.customItems.filter((item: CustomGridMenu) => item.command === 'export-text-delimited').length === 0) {
options.gridMenu.customItems.push(
{
iconCssClass: 'fa fa-download',
iconCssClass: options.gridMenu.iconExportTextDelimitedCommand || 'fa fa-download',
title: options.enableTranslate ? this.i18n.tr('EXPORT_TO_TAB_DELIMITED') : 'Export in Text format (Tab delimited)',
disabled: false,
command: 'export-text-delimited',
positionOrder: 53
positionOrder: 54
}
);
}
Expand All @@ -316,6 +336,10 @@ export class ControlAndPluginService {
this.filterService.clearFilters();
this._dataView.refresh();
break;
case 'clear-sorting':
this.sortService.clearSorting();
this._dataView.refresh();
break;
case 'export-csv':
this.exportService.exportToFile({
delimiter: DelimiterType.comma,
Expand Down
67 changes: 54 additions & 13 deletions aurelia-slickgrid/src/aurelia-slickgrid/services/sort.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ declare var Slick: any;
export class SortService {
private _currentLocalSorters: CurrentSorter[] = [];
private _eventHandler: any = new Slick.EventHandler();
private _dataView: any;
private _grid: any;
private _gridOptions: GridOption;
private _isBackendGrid = false;
private _slickSubscriber: SlickEvent = new Slick.Event();

constructor(private ea: EventAggregator) { }
Expand All @@ -21,18 +23,22 @@ export class SortService {
* @param grid SlickGrid Grid object
* @param gridOptions Grid Options object
*/
attachBackendOnSort(grid: any, gridOptions: GridOption) {
attachBackendOnSort(grid: any, dataView: any) {
this._isBackendGrid = true;
this._grid = grid;
this._gridOptions = gridOptions;
this._dataView = dataView;
if (grid) {
this._gridOptions = grid.getOptions();
}
this._slickSubscriber = grid.onSort;

// subscribe to the SlickGrid event and call the backend execution
this._slickSubscriber.subscribe(this.attachBackendOnSortSubscribe.bind(this));
this._slickSubscriber.subscribe(this.onBackendSortChanged.bind(this));
}

async attachBackendOnSortSubscribe(event: Event, args: any) {
async onBackendSortChanged(event: Event | null, args: any) {
if (!args || !args.grid) {
throw new Error('Something went wrong when trying to attach the "attachBackendOnSortSubscribe(event, args)" function, it seems that "args" is not populated correctly');
throw new Error('Something went wrong when trying to attach the "onBackendSortChanged(event, args)" function, it seems that "args" is not populated correctly');
}
const gridOptions: GridOption = args.grid.getOptions() || {};
const backendApi = gridOptions.backendServiceApi || gridOptions.onBackendEventApi;
Expand Down Expand Up @@ -66,9 +72,16 @@ export class SortService {
* @param gridOptions Grid Options object
* @param dataView
*/
attachLocalOnSort(grid: any, gridOptions: GridOption, dataView: any, columnDefinitions: Column[]) {
attachLocalOnSort(grid: any, dataView: any) {
this._isBackendGrid = false;
this._grid = grid;
this._gridOptions = gridOptions;
this._dataView = dataView;
let columnDefinitions: Column[] = [];

if (grid) {
this._gridOptions = grid.getOptions();
columnDefinitions = grid.getColumns();
}
this._slickSubscriber = grid.onSort;

this._slickSubscriber.subscribe((e: any, args: any) => {
Expand All @@ -89,16 +102,44 @@ export class SortService {
});
}

this.onLocalSortChanged(grid, gridOptions, dataView, sortColumns);
this.onLocalSortChanged(grid, this._gridOptions, dataView, sortColumns);
this.emitSortChanged('local');
});

this._eventHandler.subscribe(dataView.onRowCountChanged, (e: Event, args: any) => {
// load any presets if there are any
if (args.current > 0) {
this.loadLocalPresets(grid, gridOptions, dataView, columnDefinitions);
if (dataView && dataView.onRowCountChanged) {
this._eventHandler.subscribe(dataView.onRowCountChanged, (e: Event, args: any) => {
// load any presets if there are any
if (args.current > 0) {
this.loadLocalPresets(grid, this._gridOptions, dataView, columnDefinitions);
}
});
}
}

/**
* Clear Sorting
* - 1st, remove the SlickGrid sort icons (this setSortColumns function call really does only that)
* - 2nd, we also need to trigger a sort change
* - for a backend grid, we will trigger a backend sort changed with an empty sort columns array
* - however for a local grid, we need to pass a sort column and so we will sort by the 1st column
*/
clearSorting() {
if (this._grid && this._gridOptions && this._dataView) {
// remove any sort icons (this setSortColumns function call really does only that)
this._grid.setSortColumns([]);

// we also need to trigger a sort change
// for a backend grid, we will trigger a backend sort changed with an empty sort columns array
// however for a local grid, we need to pass a sort column and so we will sort by the 1st column
if (this._isBackendGrid) {
this.onBackendSortChanged(null, { grid: this._grid, sortCols: [] });
} else {
const columnDefinitions = this._grid.getColumns() as Column[];
if (columnDefinitions && Array.isArray(columnDefinitions)) {
this.onLocalSortChanged(this._grid, this._gridOptions, this._dataView, new Array({ sortAsc: true, sortCol: columnDefinitions[0] }));
}
}
});
}
}

getCurrentLocalSorters(): CurrentSorter[] {
Expand Down
18 changes: 14 additions & 4 deletions aurelia-slickgrid/src/examples/slickgrid/example9.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { autoinject, bindable } from 'aurelia-framework';
import { Column, FieldType, FilterType, FilterService, Formatter, Formatters, GridOption } from '../../aurelia-slickgrid';
import { Column, FieldType, FilterType, FilterService, Formatter, Formatters, GridOption, SortService } from '../../aurelia-slickgrid';

@autoinject()
export class Example9 {
Expand All @@ -22,7 +22,7 @@ export class Example9 {
dataset = [];
visibleColumns;

constructor(private filterService: FilterService) {
constructor(private filterService: FilterService, private sortService: SortService) {
// define the grid options & columns and then create the grid itself
this.defineGrid();
}
Expand Down Expand Up @@ -89,19 +89,26 @@ export class Example9 {
command: 'clear-filter',
positionOrder: 0
},
{
iconCssClass: 'fa fa-unsorted text-danger',
title: 'Clear All Sorting',
disabled: false,
command: 'clear-sorting',
positionOrder: 1
},
{
iconCssClass: 'fa fa-random',
title: 'Toggle Filter Row',
disabled: false,
command: 'toggle-filter',
positionOrder: 1
positionOrder: 2
},
{
iconCssClass: 'fa fa-random',
title: 'Toggle Top Panel',
disabled: false,
command: 'toggle-toppanel',
positionOrder: 2
positionOrder: 3
},
{
iconCssClass: 'fa fa-question-circle',
Expand All @@ -125,6 +132,9 @@ export class Example9 {
} else if (args.command === 'clear-filter') {
this.filterService.clearFilters();
this.dataviewObj.refresh();
} else if (args.command === 'clear-sorting') {
this.sortService.clearSorting();
this.dataviewObj.refresh();
} else {
alert('Command: ' + args.command);
}
Expand Down
Loading