diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 6ff16638a..8e5e4c56a 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -4,6 +4,7 @@ import { GridBasicComponent } from './examples/grid-basic.component'; import { GridClientSideComponent } from './examples/grid-clientside.component'; import { GridEditorComponent } from './examples/grid-editor.component'; import { GridFormatterComponent } from './examples/grid-formatter.component'; +import { GridGroupingComponent } from './examples/grid-grouping.component'; import { GridHeaderButtonComponent } from './examples/grid-headerbutton.component'; import { GridHeaderMenuComponent } from './examples/grid-headermenu.component'; import { GridLocalizationComponent } from './examples/grid-localization.component'; @@ -27,6 +28,7 @@ const routes: Routes = [ { path: 'headermenu', component: GridHeaderMenuComponent }, { path: 'gridgraphql', component: GridGraphqlComponent }, { path: 'gridmenu', component: GridMenuComponent }, + { path: 'grouping', component: GridGroupingComponent }, { path: 'localization', component: GridLocalizationComponent }, { path: 'clientside', component: GridClientSideComponent }, { path: 'odata', component: GridOdataComponent }, diff --git a/src/app/app.component.html b/src/app/app.component.html index 1d7669b6d..f7c907be3 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -67,6 +67,9 @@
  • 13- Backend Server Custom Paging
  • +
  • + 14- Grouping & Aggregator +
  • diff --git a/src/app/app.module.ts b/src/app/app.module.ts index c4cf4f8f5..3cad6fcf9 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -13,6 +13,7 @@ import { GridClientSideComponent } from './examples/grid-clientside.component'; import { GridEditorComponent } from './examples/grid-editor.component'; import { GridFormatterComponent } from './examples/grid-formatter.component'; import { GridGraphqlComponent } from './examples/grid-graphql.component'; +import { GridGroupingComponent } from './examples/grid-grouping.component'; import { GridHeaderButtonComponent } from './examples/grid-headerbutton.component'; import { GridHeaderMenuComponent } from './examples/grid-headermenu.component'; import { GridLocalizationComponent } from './examples/grid-localization.component'; @@ -63,6 +64,7 @@ export function appInitializerFactory(translate: TranslateService, injector: Inj GridEditorComponent, GridFormatterComponent, GridGraphqlComponent, + GridGroupingComponent, GridHeaderButtonComponent, GridHeaderMenuComponent, GridLocalizationComponent, diff --git a/src/app/examples/grid-grouping.component.html b/src/app/examples/grid-grouping.component.html new file mode 100644 index 000000000..6e48b355e --- /dev/null +++ b/src/app/examples/grid-grouping.component.html @@ -0,0 +1,45 @@ + +
    +

    {{title}}

    +
    +
    + + + + + +
    +
    +
    + + +
    +
    + + + +
    + + +
    diff --git a/src/app/examples/grid-grouping.component.ts b/src/app/examples/grid-grouping.component.ts new file mode 100644 index 000000000..1646b7506 --- /dev/null +++ b/src/app/examples/grid-grouping.component.ts @@ -0,0 +1,221 @@ +import { Component, OnInit } from '@angular/core'; +import { Column, FieldType, Formatter, Formatters, GridOption, Editors } from './../modules/angular-slickgrid'; + +// using external non-typed js libraries +declare var Slick: any; + +// create my custom Formatter with the Formatter type +const myCustomCheckmarkFormatter: Formatter = (row: number, cell: number, value: any, columnDef: Column, dataContext: any) => + value ? `` : ''; + +@Component({ + templateUrl: './grid-grouping.component.html' +}) +export class GridGroupingComponent implements OnInit { + title = 'Example 14: Grouping'; + subTitle = ` + + `; + + columnDefinitions: Column[]; + gridOptions: GridOption; + dataset: any[]; + gridObj: any; + dataviewObj: any; + sortcol = 'title'; + sortdir = 1; + percentCompleteThreshold = 0; + prevPercentCompleteThreshold = 0; + + ngOnInit(): void { + this.columnDefinitions = [ + { id: 'sel', name: '#', field: 'num', width: 40, maxWidth: 70, resizable: true, selectable: false, focusable: false }, + { id: 'title', name: 'Title', field: 'title', width: 70, minWidth: 50, cssClass: 'cell-title', sortable: true, editor: Editors.text }, + { id: 'duration', name: 'Duration', field: 'duration', width: 70, sortable: true, groupTotalsFormatter: this.sumTotalsFormatter }, + { id: '%', name: '% Complete', field: 'percentComplete', width: 80, formatter: Formatters.percentCompleteBar, sortable: true, groupTotalsFormatter: this.avgTotalsFormatter }, + { id: 'start', name: 'Start', field: 'start', minWidth: 60, sortable: true, formatter: Formatters.dateIso }, + { id: 'finish', name: 'Finish', field: 'finish', minWidth: 60, sortable: true, formatter: Formatters.dateIso }, + { id: 'cost', name: 'Cost', field: 'cost', width: 90, sortable: true, groupTotalsFormatter: this.sumTotalsFormatter }, + { id: 'effort-driven', name: 'Effort Driven', width: 80, minWidth: 20, maxWidth: 80, cssClass: 'cell-effort-driven', field: 'effortDriven', formatter: Formatters.checkmark, sortable: true } + ]; + this.gridOptions = { + autoResize: { + containerId: 'demo-container', + sidePadding: 15 + }, + enableGrouping: true + }; + + this.loadData(500); + } + + loadData(rowCount: number) { + // mock a dataset + this.dataset = []; + for (let i = 0; i < rowCount; i++) { + const randomYear = 2000 + Math.floor(Math.random() * 10); + const randomMonth = Math.floor(Math.random() * 11); + const randomDay = Math.floor((Math.random() * 29)); + const randomPercent = Math.round(Math.random() * 100); + + this.dataset[i] = { + id: 'id_' + i, + num: i, + title: 'Task ' + i, + duration: Math.round(Math.random() * 100) + '', + percentComplete: randomPercent, + percentCompleteNumber: randomPercent, + start: new Date(randomYear, randomMonth, randomDay), + finish: new Date(randomYear, (randomMonth + 1), randomDay), + cost: Math.round(Math.random() * 10000) / 100, + effortDriven: (i % 5 === 0) + }; + } + } + + gridReady(grid) { + this.gridObj = grid; + } + + dataviewReady(dataview) { + this.dataviewObj = dataview; + } + + clearGrouping() { + this.dataviewObj.setGrouping([]); + } + + collapseAllGroups() { + this.dataviewObj.collapseAllGroups(); + } + + expandAllGroups() { + this.dataviewObj.expandAllGroups(); + } + + avgTotalsFormatter(totals, columnDef) { + const val = totals.avg && totals.avg[columnDef.field]; + if (val != null) { + return 'avg: ' + Math.round(val) + '%'; + } + return ''; + } + sumTotalsFormatter(totals, columnDef) { + const val = totals.sum && totals.sum[columnDef.field]; + if (val != null) { + return 'total: ' + ((Math.round(parseFloat(val) * 100) / 100)); + } + return ''; + } + myFilter(item, args) { + return item['percentComplete'] >= args.percentComplete; + } + percentCompleteSort(a, b) { + return a['percentComplete'] - b['percentComplete']; + } + comparer(a: any, b: any) { + const x = a[this.sortcol], y = b[this.sortcol]; + return (x === y ? 0 : (x > y ? 1 : -1)); + } + groupByDuration() { + this.dataviewObj.setGrouping({ + getter: 'duration', + formatter: (g) => { + return `Duration: ${g.value} (${g.count} items)`; + }, + aggregators: [ + new Slick.Data.Aggregators.Avg('percentComplete'), + new Slick.Data.Aggregators.Sum('cost') + ], + aggregateCollapsed: false, + lazyTotalsCalculation: true + }); + } + groupByDurationOrderByCount(aggregateCollapsed) { + this.dataviewObj.setGrouping({ + getter: 'duration', + formatter: (g) => { + return `Duration: ${g.value} (${g.count} items)`; + }, + comparer: (a, b) => { + return a.count - b.count; + }, + aggregators: [ + new Slick.Data.Aggregators.Avg('percentComplete'), + new Slick.Data.Aggregators.Sum('cost') + ], + aggregateCollapsed, + lazyTotalsCalculation: true + }); + } + groupByDurationEffortDriven() { + this.dataviewObj.setGrouping([ + { + getter: 'duration', + formatter: (g) => { + return `Duration: ${g.value} (${g.count} items)`; + }, + aggregators: [ + new Slick.Data.Aggregators.Sum('duration'), + new Slick.Data.Aggregators.Sum('cost') + ], + aggregateCollapsed: true, + lazyTotalsCalculation: true + }, + { + getter: 'effortDriven', + formatter: (g) => { + return `Effort-Driven: ${(g.value ? 'True' : 'False')} (${g.count} items)`; + }, + aggregators: [ + new Slick.Data.Aggregators.Avg('percentComplete'), + new Slick.Data.Aggregators.Sum('cost') + ], + collapsed: true, + lazyTotalsCalculation: true + } + ]); + } + groupByDurationEffortDrivenPercent() { + this.dataviewObj.setGrouping([ + { + getter: 'duration', + formatter: (g) => { + return `Duration: ${g.value} (${g.count} items)`; + }, + aggregators: [ + new Slick.Data.Aggregators.Sum('duration'), + new Slick.Data.Aggregators.Sum('cost') + ], + aggregateCollapsed: true, + lazyTotalsCalculation: true + }, + { + getter: 'effortDriven', + formatter: (g) => { + return `Effort-Driven: ${(g.value ? 'True' : 'False')} (${g.count} items)`; + }, + aggregators: [ + new Slick.Data.Aggregators.Sum('duration'), + new Slick.Data.Aggregators.Sum('cost') + ], + lazyTotalsCalculation: true + }, + { + getter: 'percentComplete', + formatter: (g) => { + return `% Complete: ${g.value} (${g.count} items)`; + }, + aggregators: [ + new Slick.Data.Aggregators.Avg('percentComplete') + ], + aggregateCollapsed: true, + collapsed: true, + lazyTotalsCalculation: true + } + ]); + } +} diff --git a/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.ts b/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.ts index 190ad3163..9f9b005a0 100644 --- a/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.ts +++ b/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.ts @@ -6,6 +6,7 @@ import 'slickgrid/slick.core'; import 'slickgrid/slick.dataview'; import 'slickgrid/slick.grid'; import 'slickgrid/slick.dataview'; +import 'slickgrid/slick.groupitemmetadataprovider.js'; import 'slickgrid/controls/slick.columnpicker'; import 'slickgrid/controls/slick.gridmenu'; import 'slickgrid/controls/slick.pager'; @@ -60,6 +61,7 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn gridHeightString: string; gridWidthString: string; groupingDefinition: any = {}; + groupItemMetadataProvider: any; showPagination = false; isGridInitialized = false; @@ -150,11 +152,23 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn this.gridOptions = this.mergeGridOptions(this.gridOptions); this.createBackendApiInternalPostProcessCallback(this.gridOptions); - this._dataView = new Slick.Data.DataView(); + if (this.gridOptions.enableGrouping) { + this.groupItemMetadataProvider = new Slick.Data.GroupItemMetadataProvider(); + this.sharedService.groupItemMetadataProvider = this.groupItemMetadataProvider; + this._dataView = new Slick.Data.DataView({ + groupItemMetadataProvider: this.groupItemMetadataProvider, + inlineFilters: true + }); + } else { + this._dataView = new Slick.Data.DataView(); + } this.controlAndPluginService.createPluginBeforeGridCreation(this._columnDefinitions, this.gridOptions); this.grid = new Slick.Grid(`#${this.gridId}`, this._dataView, this._columnDefinitions, this.gridOptions); - this.controlAndPluginService.attachDifferentControlOrPlugins(this.grid, this._columnDefinitions, this.gridOptions, this._dataView); + // pass all necessary options to the shared service + this.sharedService.init(this.grid, this._dataView, this.gridOptions, this._columnDefinitions); + + this.controlAndPluginService.attachDifferentControlOrPlugins(); this.attachDifferentHooks(this.grid, this.gridOptions, this._dataView); // emit the Grid & DataView object to make them available in parent component @@ -166,9 +180,6 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn this._dataView.setItems(this._dataset, this.gridOptions.datasetIdPropertyName); this._dataView.endUpdate(); - // pass all necessary options to the shared service - this.sharedService.init(this.grid, this._dataView, this.gridOptions, this._columnDefinitions); - // attach resize ONLY after the dataView is ready this.attachResizeHook(this.grid, this.gridOptions); diff --git a/src/app/modules/angular-slickgrid/models/column.interface.ts b/src/app/modules/angular-slickgrid/models/column.interface.ts index fc5c00f6c..6d0668300 100644 --- a/src/app/modules/angular-slickgrid/models/column.interface.ts +++ b/src/app/modules/angular-slickgrid/models/column.interface.ts @@ -2,6 +2,7 @@ import { ColumnFilter } from './columnFilter.interface'; import { Editor } from './editor.interface'; import { FieldType } from './fieldType'; import { Formatter } from './formatter.interface'; +import { GroupFormatter } from './groupFormatter.interface'; import { HeaderButtonItem } from './headerButtonItem.interface'; import { HeaderMenuItem } from './headerMenuItem.interface'; import { OnEventArgs } from './onEventArgs.interface'; @@ -73,9 +74,12 @@ export interface Column { /** are we allowed to focus on the column? */ focusable?: boolean; - /** Custom Sorter function that can be provided to the column */ + /** Formatter function that can be used to change and format certain column(s) in the grid */ formatter?: Formatter; + /** Group Totals Formatter function that can be used to add grouping totals in the grid */ + groupTotalsFormatter?: GroupFormatter; + /** Options that can be provide to the Header Menu Plugin */ header?: { /** list of Buttons to show in the header */ diff --git a/src/app/modules/angular-slickgrid/models/gridOption.interface.ts b/src/app/modules/angular-slickgrid/models/gridOption.interface.ts index 6131afa14..b9deb4af0 100644 --- a/src/app/modules/angular-slickgrid/models/gridOption.interface.ts +++ b/src/app/modules/angular-slickgrid/models/gridOption.interface.ts @@ -91,6 +91,9 @@ export interface GridOption { /** Do we want to enable the Export to File? (if Yes, it will show up in the Grid Menu) */ enableExport?: boolean; + /** Defaults to false, do we want to enable the Grouping & Aggregator? */ + enableGrouping?: boolean; + /** Defaults to false, which leads to all Formatters of the grid being evaluated on export. You can also override a column by changing the propery on the column itself */ exportWithFormatter?: boolean; diff --git a/src/app/modules/angular-slickgrid/models/groupFormatter.interface.ts b/src/app/modules/angular-slickgrid/models/groupFormatter.interface.ts new file mode 100644 index 000000000..a8ee46f4d --- /dev/null +++ b/src/app/modules/angular-slickgrid/models/groupFormatter.interface.ts @@ -0,0 +1,3 @@ +import { Column } from './column.interface'; + +export type GroupFormatter = (totals: any, columnDef: Column) => string; diff --git a/src/app/modules/angular-slickgrid/models/index.ts b/src/app/modules/angular-slickgrid/models/index.ts index c72eace23..ab07d9f78 100644 --- a/src/app/modules/angular-slickgrid/models/index.ts +++ b/src/app/modules/angular-slickgrid/models/index.ts @@ -35,6 +35,7 @@ export * from './graphqlPaginationOption.interface'; export * from './graphqlResult.interface'; export * from './graphqlServiceOption.interface'; export * from './graphqlSortingOption.interface'; +export * from './groupFormatter.interface'; export * from './customGridMenu.interface'; export * from './gridMenu.interface'; export * from './gridOption.interface'; diff --git a/src/app/modules/angular-slickgrid/services/controlAndPlugin.service.ts b/src/app/modules/angular-slickgrid/services/controlAndPlugin.service.ts index 00a087394..fc515c5ae 100644 --- a/src/app/modules/angular-slickgrid/services/controlAndPlugin.service.ts +++ b/src/app/modules/angular-slickgrid/services/controlAndPlugin.service.ts @@ -16,6 +16,7 @@ import { } from './../models/index'; import { TranslateService } from '@ngx-translate/core'; import { castToPromise } from './../services/utilities'; +import { SharedService } from './shared.service'; // using external non-typed js libraries declare var Slick: any; @@ -38,7 +39,7 @@ export class ControlAndPluginService { gridMenuControl: any; rowSelectionPlugin: any; - constructor(private exportService: ExportService, private filterService: FilterService, private translate: TranslateService) { } + constructor(private exportService: ExportService, private filterService: FilterService, private sharedService: SharedService, private translate: TranslateService) { } /** * Attach/Create different Controls or Plugins after the Grid is created @@ -47,72 +48,78 @@ export class ControlAndPluginService { * @param options * @param dataView */ - attachDifferentControlOrPlugins(grid: any, columnDefinitions: Column[], options: GridOption, dataView: any) { - this._grid = grid; - this._gridOptions = options; - this._dataView = dataView; - this._columnDefinitions = columnDefinitions; - this.visibleColumns = columnDefinitions; - - if (options.enableColumnPicker) { - this.columnPickerControl = this.createColumnPicker(grid, columnDefinitions, options); + attachDifferentControlOrPlugins() { + this._grid = this.sharedService.grid; + this._gridOptions = this.sharedService.gridOptions; + this._dataView = this.sharedService.dataView; + this._columnDefinitions = this.sharedService.columnDefinitions; + this.visibleColumns = this.sharedService.columnDefinitions; + + if (this._gridOptions.enableColumnPicker) { + this.columnPickerControl = this.createColumnPicker(this._grid, this._columnDefinitions, this._gridOptions); } - if (options.enableGridMenu) { - this.gridMenuControl = this.createGridMenu(grid, columnDefinitions, options); + if (this._gridOptions.enableGridMenu) { + this.gridMenuControl = this.createGridMenu(this._grid, this._columnDefinitions, this._gridOptions); } - if (options.enableAutoTooltip) { - this.autoTooltipPlugin = new Slick.AutoTooltips(options.autoTooltipOptions || {}); - grid.registerPlugin(this.autoTooltipPlugin); + if (this._gridOptions.enableAutoTooltip) { + this.autoTooltipPlugin = new Slick.AutoTooltips(this._gridOptions.autoTooltipOptions || {}); + this._grid.registerPlugin(this.autoTooltipPlugin); } - if (options.enableCheckboxSelector) { + // register the group item metadata provider to add expand/collapse group handlers + if (this._gridOptions.enableGrouping) { + const groupItemMetaProvider = this.sharedService.groupItemMetadataProvider || {}; + this._grid.registerPlugin(groupItemMetaProvider); + } + + if (this._gridOptions.enableCheckboxSelector) { // when enabling the Checkbox Selector Plugin, we need to also watch onClick events to perform certain actions // the selector column has to be create BEFORE the grid (else it behaves oddly), but we can only watch grid events AFTER the grid is created - grid.registerPlugin(this.checkboxSelectorPlugin); + this._grid.registerPlugin(this.checkboxSelectorPlugin); // this also requires the Row Selection Model to be registered as well if (!this.rowSelectionPlugin) { - this.rowSelectionPlugin = new Slick.RowSelectionModel(options.rowSelectionOptions || {}); - grid.setSelectionModel(this.rowSelectionPlugin); + this.rowSelectionPlugin = new Slick.RowSelectionModel(this._gridOptions.rowSelectionOptions || {}); + this._grid.setSelectionModel(this.rowSelectionPlugin); } } - if (options.enableRowSelection) { - this.rowSelectionPlugin = new Slick.RowSelectionModel(options.rowSelectionOptions || {}); - grid.setSelectionModel(this.rowSelectionPlugin); + if (this._gridOptions.enableRowSelection) { + this.rowSelectionPlugin = new Slick.RowSelectionModel(this._gridOptions.rowSelectionOptions || {}); + this._grid.setSelectionModel(this.rowSelectionPlugin); } - if (options.enableHeaderButton) { - this.headerButtonsPlugin = new Slick.Plugins.HeaderButtons(options.headerButton || {}); - grid.registerPlugin(this.headerButtonsPlugin); + if (this._gridOptions.enableHeaderButton) { + this.headerButtonsPlugin = new Slick.Plugins.HeaderButtons(this._gridOptions.headerButton || {}); + this._grid.registerPlugin(this.headerButtonsPlugin); this.headerButtonsPlugin.onCommand.subscribe((e: Event, args: HeaderButtonOnCommandArgs) => { - if (options.headerButton && typeof options.headerButton.onCommand === 'function') { - options.headerButton.onCommand(e, args); + if (this._gridOptions.headerButton && typeof this._gridOptions.headerButton.onCommand === 'function') { + this._gridOptions.headerButton.onCommand(e, args); } }); } - if (options.enableHeaderMenu) { - const headerMenuOptions = options.headerMenu || {}; + if (this._gridOptions.enableHeaderMenu) { + const headerMenuOptions = this._gridOptions.headerMenu || {}; headerMenuOptions.minWidth = headerMenuOptions.minWidth || 140; headerMenuOptions.autoAlignOffset = headerMenuOptions.autoAlignOffset || 12; this.headerMenuPlugin = new Slick.Plugins.HeaderMenu(headerMenuOptions); - grid.registerPlugin(this.headerMenuPlugin); + this._grid.registerPlugin(this.headerMenuPlugin); this.headerMenuPlugin.onCommand.subscribe((e: Event, args: HeaderMenuOnCommandArgs) => { - if (options.headerMenu && typeof options.headerMenu.onCommand === 'function') { - options.headerMenu.onCommand(e, args); + if (this._gridOptions.headerMenu && typeof this._gridOptions.headerMenu.onCommand === 'function') { + this._gridOptions.headerMenu.onCommand(e, args); } }); this.headerMenuPlugin.onCommand.subscribe((e: Event, args: HeaderMenuOnBeforeMenuShowArgs) => { - if (options.headerMenu && typeof options.headerMenu.onBeforeMenuShow === 'function') { - options.headerMenu.onBeforeMenuShow(e, args); + if (this._gridOptions.headerMenu && typeof this._gridOptions.headerMenu.onBeforeMenuShow === 'function') { + this._gridOptions.headerMenu.onBeforeMenuShow(e, args); } }); } - if (options.registerPlugins !== undefined) { - if (Array.isArray(options.registerPlugins)) { - options.registerPlugins.forEach((plugin) => { - grid.registerPlugin(plugin); + if (this._gridOptions.registerPlugins !== undefined) { + if (Array.isArray(this._gridOptions.registerPlugins)) { + this._gridOptions.registerPlugins.forEach((plugin) => { + this._grid.registerPlugin(plugin); }); } else { - grid.registerPlugin(options.registerPlugins); + this._grid.registerPlugin(this._gridOptions.registerPlugins); } } } diff --git a/src/app/modules/angular-slickgrid/services/shared.service.ts b/src/app/modules/angular-slickgrid/services/shared.service.ts index d5f689b98..ffda4eb5f 100644 --- a/src/app/modules/angular-slickgrid/services/shared.service.ts +++ b/src/app/modules/angular-slickgrid/services/shared.service.ts @@ -5,6 +5,7 @@ export class SharedService { grid: any; gridOptions: GridOption; columnDefinitions: Column[]; + groupItemMetadataProvider: any; init(grid: any, dataView: any, gridOptions: GridOption, columnDefinitions: Column[]) { this.grid = grid; diff --git a/src/app/modules/angular-slickgrid/styles/_variables.scss b/src/app/modules/angular-slickgrid/styles/_variables.scss index 11b39494f..b5cd56624 100644 --- a/src/app/modules/angular-slickgrid/styles/_variables.scss +++ b/src/app/modules/angular-slickgrid/styles/_variables.scss @@ -72,6 +72,9 @@ $header-scroll-width-to-remove: 16px !default; // /* icon font is using Font-Awesome by default but could be changed to any other icon package like Glyphicons, ... */ $icon-font-family: "FontAwesome" !default; // or Glyphicons Halflings */ $icon-font-size: 14px !default; +$icon-group-expanded: "\f147" !default; +$icon-group-collapsed: "\f196" !default; +$icon-group-font-size: $icon-font-size !default; $icon-sort-asc: "\f0d8" !default; $icon-sort-desc: "\f0d7" !default; $icon-sort-color: rgb(76, 128, 190) !default; diff --git a/src/app/modules/angular-slickgrid/styles/slick-default-theme.scss b/src/app/modules/angular-slickgrid/styles/slick-default-theme.scss index 2d467eb2b..3bca4b894 100644 --- a/src/app/modules/angular-slickgrid/styles/slick-default-theme.scss +++ b/src/app/modules/angular-slickgrid/styles/slick-default-theme.scss @@ -138,11 +138,17 @@ margin-right: 5px; &.expanded:before { - content: "\f196"; + content: $icon-group-expanded; + font-family: $icon-font-family; + font-size: $icon-group-font-size; + cursor: pointer; } &.collapsed:before { - content: "\f147"; + content: $icon-group-collapsed; + font-family: $icon-font-family; + font-size: $icon-group-font-size; + cursor: pointer; } }