|
1 | | -#### index |
2 | | -- [Description](#descriptions) |
3 | | -- [Grid State](#grid-state-1) |
4 | | -- [Grid Presets](#grid-presets) |
5 | | -- [Grid State Event](#grid-state-event) |
6 | | -- [How to Load Grid with Certain Columns Hidden](#how-to-load-grid-with-certain-columns-preset-example-hide-certain-columns-on-load) |
| 1 | +The `Grid Menu` (also known as the `Hamburger Menu`) is now part of `Angular-Slickgrid` and is enabled by default). |
7 | 2 |
|
8 | | -## Demo |
9 | | -Look at your developer console before leaving the page |
10 | | -#### Regular grid |
11 | | -[Demo Page](https://ghiscoding.github.io/Angular-Slickgrid/#/clientside) / [Demo Component](https://github.com/ghiscoding/angular-slickgrid/blob/master/src/app/examples/grid-clientside.component.ts) |
| 3 | +## How to use it? |
| 4 | +#### It's Enabled by default |
| 5 | +Technically, it's enable by default and so you don't have anything to do to enjoy it. However if you want to customize the content of the Grid Menu, then continue reading. |
12 | 6 |
|
13 | | -#### with Backend Service |
14 | | -[Demo Page](https://ghiscoding.github.io/Angular-Slickgrid/#/gridgraphql) / [Demo Component](https://github.com/ghiscoding/angular-slickgrid/blob/master/src/app/examples/grid-graphql.component.ts) |
| 7 | +### Demo |
| 8 | +[Demo Page](https://ghiscoding.github.io/Angular-Slickgrid/#/gridmenu) / [Demo Component](https://github.com/ghiscoding/angular-slickgrid/blob/master/src/app/examples/grid-menu.component.ts) |
15 | 9 |
|
16 | | -## Descriptions |
17 | | -#### Grid State |
18 | | -The `Grid State` are what we defined as the currently used `Columns` / `Filters` / `Sorters` / `Pagination` of the actual grid (pagination is only returned when used with Backend Service API). The columns also include their (size, position order & visibility (show/hidden)). |
19 | | -#### Presets |
20 | | -Presets can be used to preset a grid with certain `Columns` / `Filters` / `Sorters` / `Pagination`. When we say `Columns`, we actually mean their size, order position and visibility (shown/hidden) in the grid. |
21 | | -#### Combining the two together |
22 | | -So basically, the idea is to save the `Grid State` in Local Storage (or DB) before the grid gets destroyed and once we come back to that same page we can preset the grid with the exact same state as it was before leaving the page (just like if we were doing a forward/back button with browser history). |
| 10 | +## Customization |
| 11 | +### Column Picker |
| 12 | +The Grid Menu comes, by default, with a `Column Picker`. This brings an easy way to show/hide certain column(s) from the grid. This functionality was copied from the [Column Picker Plugin](https://github.com/ghiscoding/angular-slickgrid/wiki/SlickGrid-Controls-&-Plugins#column-picker) and brought over to the Grid Menu. |
23 | 13 |
|
24 | | -## Grid State |
25 | | -You can get the `Grid State` at any point in time. However if you wish to save the grid state before leaving the page and store that in Local Storage, then the best way is to use the `onBeforeGridDestroy` Event Emitter. |
| 14 | +### Custom Commands |
26 | 15 |
|
27 | | -##### View |
28 | | -```html |
29 | | -<angular-slickgrid |
30 | | - gridId="grid2" |
31 | | - [columnDefinitions]="columnDefinitions" |
32 | | - [gridOptions]="gridOptions" |
33 | | - [dataset]="dataset" |
34 | | - (onAngularGridCreated)="angularGridReady($event.detail)" |
35 | | - (onBeforeGridDestroy)="saveCurrentGridState($event)"> |
36 | | -</angular-slickgrid> |
37 | | -``` |
38 | | - |
39 | | -##### Component |
40 | | -```typescript |
41 | | -import { GridState } from 'angular-slickgrid'; |
42 | | - |
43 | | -@Component({ |
44 | | - templateUrl: './grid-demo.component.html' |
45 | | -}) |
46 | | -export class GridDemoComponent { |
47 | | - angularGrid: AngularGridInstance; |
48 | | - |
49 | | - angularGridReady(angularGrid: AngularGridInstance) { |
50 | | - this.angularGrid = angularGrid; |
51 | | - } |
52 | | - |
53 | | - // you can save it to Local Storage of DB in this call |
54 | | - saveCurrentGridState(grid) { |
55 | | - const gridState: GridState = this.angularGrid.gridStateService.getCurrentGridState(); |
56 | | - console.log('Leaving page with current grid state', gridState); |
57 | | - } |
58 | | -} |
59 | | -``` |
60 | | - |
61 | | -### Using Grid Presets & Filter SearchTerm(s) |
62 | | -What happens when we use the grid `presets` and a [Filter Default SearchTerms](../column-functionalities/filters/select-filter.md#default-search-terms)? In this case, the `presets` will win over filter `searchTerms`. The cascading order of priorities is the following |
63 | | -1. Do we have any `presets`? Yes use them, else go to step 2 |
64 | | -2. Do we have any Filter `searchTerms`? Yes use them, else go to step 3 |
65 | | -3. No `presets` and no `searchTerms`, load grid with default grid & column definitions |
66 | | - |
67 | | -## Grid Presets |
68 | | -### Structure |
69 | | -The current structure of a Grid Presets is the following |
70 | | -```typescript |
71 | | -export interface CurrentColumn { |
72 | | - columnId: string; |
73 | | - cssClass?: string; |
74 | | - headerCssClass?: string; |
75 | | - width?: number; |
76 | | -} |
77 | | -export interface CurrentFilter { |
78 | | - columnId: string; |
79 | | - operator?: OperatorType | OperatorString; |
80 | | - searchTerms?: SearchTerm[]; |
81 | | -} |
82 | | -export interface CurrentSorter { |
83 | | - columnId: string; |
84 | | - direction: SortDirection | SortDirectionString; |
85 | | -} |
86 | | -export interface GridState { |
87 | | - columns?: CurrentColumn[] | null; |
88 | | - filters?: CurrentFilter[] | null; |
89 | | - sorters?: CurrentSorter[] | null; |
90 | | - pagination?: { |
91 | | - pageNumber: number; |
92 | | - pageSize: number; |
93 | | - }; |
94 | | -} |
95 | | -``` |
96 | | - |
97 | | -#### Example |
98 | | -For example, we can set `presets` on a grid like so: |
99 | | -**Component** |
100 | | -```typescript |
101 | | -import { GridState } from 'angular-slickgrid'; |
102 | | - |
103 | | -@Component({ |
104 | | - templateUrl: './grid-demo.component.html' |
105 | | -}) |
106 | | -export class GridDemoComponent { |
107 | | - angularGrid: AngularGridInstance; |
108 | | - |
109 | | - ngOnInit(): void { |
110 | | - this.columnDefinitions = [ |
111 | | - { id: 'name', name: 'Name', field: 'name', filterable: true, sortable: true, sortable: true }, |
112 | | - { id: 'duration', name: 'Duration', field: 'duration', filterable: true, sortable: true }, |
113 | | - { id: 'complete', name: '% Complete', field: 'percentComplete', filterable: true, sortable: true }, |
114 | | - ]; |
115 | | - |
116 | | - this.gridOptions = { |
117 | | - enableFiltering: true, |
118 | | - |
119 | | - // use columnDef searchTerms OR use presets as shown below |
120 | | - presets: { |
121 | | - // the column position in the array is very important and represent |
122 | | - // the position that will show in the grid |
123 | | - columns: [ |
124 | | - { columnId: 'duration', width: 88, headerCssClass: 'customHeaderClass' }, |
125 | | - { columnId: 'complete', width: 57 } |
126 | | - ], |
127 | | - filters: [ |
128 | | - { columnId: 'duration', searchTerms: [2, 22, 44] }, |
129 | | - { columnId: 'complete', searchTerms: ['>5'] } |
130 | | - ], |
131 | | - sorters: [ |
132 | | - { columnId: 'duration', direction: 'DESC' }, |
133 | | - { columnId: 'complete', direction: 'ASC' } |
134 | | - ], |
135 | | - |
136 | | - // with Backend Service ONLY, you can also add Pagination info |
137 | | - pagination: { pageNumber: 2, pageSize: 20 } |
138 | | - } |
139 | | - }; |
140 | | -} |
141 | | -``` |
142 | | -
|
143 | | -### Grid State Event |
144 | | -There are 2 ways of subscribing to GridState Service event changed. |
145 | | -1. Through `(onGridStateChanged)` Event Emitter (recommended) |
146 | | -2. Through `onGridStateChanged` Observable on the GridState Service. |
| 16 | +The Grid Menu also comes, by default, with a list of built-in custom commands (all their `positionOrder` are in the reserved range of 40 to 60) |
| 17 | +- Clear all Filters (you can hide it with `hideClearAllFiltersCommand: true`) |
| 18 | +- Clear all Sorting (you can hide it with `hideClearAllSortingCommand: true`) |
| 19 | +- Toggle the Filter Row (you can hide it with `hideToggleFilterCommand: true`) |
| 20 | +- _Export to CSV_ (you can hide it with `hideExportCsvCommand: true`) |
| 21 | +- _Export to Text Delimited (you can hide it with `hideExportTextDelimitedCommand: true`) |
| 22 | +- _Refresh Dataset_, only shown when using Backend Service API (you can hide it with `hideRefreshDatasetCommand: true`) |
147 | 23 |
|
148 | | -Examples |
149 | | -#### 1. `(onGridStateChanged)` Event Emitter (recommended) |
150 | | -##### View |
151 | | -```html |
152 | | -<angular-slickgrid gridId="grid1" |
153 | | - [columnDefinitions]="columnDefinitions" |
154 | | - [gridOptions]="gridOptions" |
155 | | - [dataset]="dataset" |
156 | | - (onGridStateChanged)="gridStateChanged($event)"> |
157 | | -</angular-slickgrid> |
158 | | -``` |
159 | | -##### Component |
160 | | -```typescript |
161 | | -import { GridStateChange } from 'angular-slickgrid'; |
162 | | -
|
163 | | -export class ExampleComponent implements OnInit { |
164 | | - gridStateChanged(gridState: GridStateChange) { |
165 | | - console.log('Grid State changed:: ', gridState); |
166 | | - } |
167 | | -} |
168 | | -``` |
169 | | - |
170 | | -#### 2. Through `onGridStateChanged` Observable on the GridState Service |
171 | | -##### View |
172 | | -```html |
173 | | -<angular-slickgrid |
174 | | - gridId="grid2" |
175 | | - [columnDefinitions]="columnDefinitions" |
176 | | - [gridOptions]="gridOptions" |
177 | | - [dataset]="dataset" |
178 | | - (onAngularGridCreated)="angularGridReady($event.detail)" |
179 | | - (onBeforeGridDestroy)="saveCurrentGridState($event)"> |
180 | | -</angular-slickgrid> |
| 24 | +This section is called Custom Commands because you can also customize this section with your own commands. To do that, you need to fill in 2 properties (an array of `commandItems` and define `onGridMenuCommand` callback) in your Grid Options. For example, `Angular-Slickgrid` is configured by default with these settings (you can overwrite any one of them): |
| 25 | +```javascript |
| 26 | +this.gridOptions = { |
| 27 | + enableAutoResize: true, |
| 28 | + enableGridMenu: true, // <<-- this will automatically add extra custom commands |
| 29 | + enableFiltering: true, |
| 30 | + gridMenu: { |
| 31 | + commandTitle: 'Custom Commands', |
| 32 | + columnTitle: 'Columns', |
| 33 | + iconCssClass: 'fa fa-ellipsis-v', |
| 34 | + menuWidth: 17, |
| 35 | + resizeOnShowHeaderRow: true, |
| 36 | + commandItems: [ |
| 37 | + { |
| 38 | + iconCssClass: 'fa fa-filter text-danger', |
| 39 | + title: 'Clear All Filters', |
| 40 | + disabled: false, |
| 41 | + command: 'clear-filter' |
| 42 | + }, |
| 43 | + { |
| 44 | + iconCssClass: 'fa fa-random', |
| 45 | + title: 'Toggle Filter Row', |
| 46 | + disabled: false, |
| 47 | + command: 'toggle-filter' |
| 48 | + }, |
| 49 | + // you can add sub-menus by adding nested `commandItems` |
| 50 | + { |
| 51 | + // we can also have multiple nested sub-menus |
| 52 | + command: 'export', title: 'Exports', positionOrder: 99, |
| 53 | + commandItems: [ |
| 54 | + { command: 'exports-txt', title: 'Text (tab delimited)' }, |
| 55 | + { |
| 56 | + command: 'sub-menu', title: 'Excel', cssClass: 'green', subMenuTitle: 'available formats', subMenuTitleCssClass: 'text-italic orange', |
| 57 | + commandItems: [ |
| 58 | + { command: 'exports-csv', title: 'Excel (csv)' }, |
| 59 | + { command: 'exports-xlsx', title: 'Excel (xlsx)' }, |
| 60 | + ] |
| 61 | + } |
| 62 | + ] |
| 63 | + }, |
| 64 | + ], |
| 65 | + onCommand: (e, args) => { |
| 66 | + if (args.command === 'toggle-filter') { |
| 67 | + this.gridObj.setHeaderRowVisibility(!this.gridObj.getOptions().showHeaderRow); |
| 68 | + } else if (args.command === 'clear-filter') { |
| 69 | + this.filterService.clearFilters(); |
| 70 | + this.dataviewObj.refresh(); |
| 71 | + } |
| 72 | + } |
| 73 | + } |
| 74 | +}; |
181 | 75 | ``` |
182 | 76 |
|
183 | | -##### Component |
184 | | -```typescript |
185 | | -import { AngularGridInstance, GridStateChange } from 'angular-slickgrid'; |
186 | | -
|
187 | | -export class ExampleComponent implements OnInit, OnDestroy { |
188 | | - angularGrid: AngularGridInstance; |
189 | | - gridStateSub: Subscription; |
| 77 | +#### Events |
190 | 78 |
|
191 | | - angularGridReady(angularGrid: AngularGridInstance) { |
192 | | - this.angularGrid = angularGrid; |
193 | | - this.gridStateSub = this.angularGrid.gridStateService.onGridStateChanged.subscribe((data: GridStateChange) => console.log(data)); |
194 | | - } |
| 79 | +There are multiple events/callback hooks which are accessible from the Grid Options |
| 80 | +- `onBeforeMenuShow` |
| 81 | +- `onAfterMenuShow` |
| 82 | +- `onMenuClose` |
| 83 | +- `onColumnsChanged` |
| 84 | +- `onCommand` |
195 | 85 |
|
196 | | - ngOnDestroy() { |
197 | | - this.gridStateSub.unsubscribe(); |
198 | | - } |
199 | | -} |
| 86 | +```ts |
| 87 | +gridMenu: { |
| 88 | + // commandItems: [ |
| 89 | + // { command: 'help', title: 'Help', positionOrder: 70, action: (e, args) => console.log(args) }, |
| 90 | + // { command: '', divider: true, positionOrder: 72 }, |
| 91 | + // { command: 'hello', title: 'Hello', positionOrder: 69, action: (e, args) => alert('Hello World'), cssClass: 'red', tooltip: 'Hello World', iconCssClass: 'mdi mdi-close' }, |
| 92 | + // ], |
| 93 | + // menuUsabilityOverride: () => false, |
| 94 | + onBeforeMenuShow: () => { |
| 95 | + console.log('onGridMenuBeforeMenuShow'); |
| 96 | + // return false; // returning false would prevent the grid menu from opening |
| 97 | + }, |
| 98 | + onAfterMenuShow: () => console.log('onGridMenuAfterMenuShow'), |
| 99 | + onColumnsChanged: (_e, args) => console.log('onGridMenuColumnsChanged', args), |
| 100 | + onCommand: (e, args) => { |
| 101 | + // e.preventDefault(); // preventing default event would keep the menu open after the execution |
| 102 | + console.log('onGridMenuCommand', args.command); |
| 103 | + }, |
| 104 | + onMenuClose: (e, args) => console.log('onGridMenuMenuClose - visible columns count', args.visibleColumns.length), |
| 105 | +}, |
200 | 106 | ``` |
201 | 107 |
|
202 | | -## How to Load Grid with certain Columns Preset (example hide certain Column(s) on load) |
203 | | -You can show/hide or even change column position all via the `presets`, yes `presets` is that powerful. All you need is to pass all Columns that you want to show as part of the `columns` property of `presets`. Typically you already have the entire columns definition since you just defined it, so you can re-use that and just use `map` to loop through and populate the `columns` according to the structure needed (see [preset structure](#structure)). What you have to know is that whatever array you pass will drive what the user will see and at which order the columns will show (basically the array order does matter). If a Columns is omitted from that array, then it will become a hidden column (you can still show it through Grid Menu or Column Picker). |
204 | | - |
205 | | -So let say that we want to hide the last Column on page load, we can just find the column by it's `id` that you want to hide and pass the new column definition to the `presets` (again make sure to follow the correct preset structure). |
206 | | - |
207 | | -##### Component |
208 | | -```ts |
209 | | -this.columnDefinitions = [ |
210 | | - // your definition |
211 | | -]; |
| 108 | +For more info on all the available properties of the custom commands, you can read refer to the doc written in the Grid Menu [implementation](https://github.com/6pac/SlickGrid/blob/master/controls/slick.gridmenu.js) itself. |
212 | 109 |
|
213 | | -// for example, let's hide last column, we can just use `pop()` last column |
214 | | -// and use `map()` to only pull required field for presets to work |
215 | | -const mappedColumnDefinitions = this.columnDefinitions.map((col) => { |
216 | | - return { columnId: col.id, width: col.width }; |
217 | | -}); |
218 | | -mappedColumnDefinitions.pop(); |
| 110 | +### How to change an icon of all default commands? |
219 | 111 |
|
220 | | -// then pass it to the presets |
| 112 | +You can change any of the default command icon(s) by changing the `icon[Command]`, for example, see below for the defaults. |
| 113 | +```javascript |
221 | 114 | this.gridOptions = { |
222 | | - presets: { |
223 | | - columns: mappedColumnDefinitions |
224 | | - } |
| 115 | + enableGridMenu: true, |
| 116 | + gridMenu: { |
| 117 | + iconClearAllFiltersCommand: 'fa fa-filter text-danger' |
| 118 | + iconClearAllSortingCommand: 'fa fa-unsorted text-danger', |
| 119 | + iconExportCsvCommand: 'fa fa-download', |
| 120 | + iconExportTextDelimitedCommand: 'fa fa-download', |
| 121 | + iconRefreshDatasetCommand: 'fa fa-refresh', |
| 122 | + iconToggleFilterCommand: 'fa fa-random', |
| 123 | + }, |
225 | 124 | }; |
226 | 125 | ``` |
227 | | -This would be the easiest way to do it. |
228 | 126 |
|
229 | | -As pointed out earlier, the `presets` requires a specific structure where the `columns` is the list of columns to show/hide with their possible widths and also the position in the array is very important as it defines the position shown in the UI |
230 | | -```ts |
231 | | -this.gridOptions = { |
232 | | - enableFiltering: true, |
| 127 | +### How to Disable the Grid Menu? |
233 | 128 |
|
234 | | - // use columnDef searchTerms OR use presets as shown below |
235 | | - presets: { |
236 | | - // the column position in the array is very important and represent |
237 | | - // the position that will show in the grid |
238 | | - columns: [ |
239 | | - { columnId: 'duration', width: 88, headerCssClass: 'customHeaderClass' }, |
240 | | - { columnId: 'complete', width: 57 } |
241 | | - ], |
242 | | - } |
| 129 | +You can disable the Grid Menu, by calling `enableGridMenu: false` from the Grid Options. |
| 130 | +```javascript |
| 131 | +this.gridOptions = { |
| 132 | + enableGridMenu: false |
243 | 133 | }; |
244 | 134 | ``` |
245 | | -You could technically redefine by hand the complete list of `columns` that the `presets` requires. I would personally do it via the Column Definitions looping with `map()`, but go manual is also perfectly fine. You would just re-declare the `columns` again with the `id` and `width` and that would work as well. |
0 commit comments