Skip to content
This repository was archived by the owner on Jun 1, 2025. It is now read-only.

feat(frozen): add Frozen/Pinned rows/columns Feature #93

Merged
merged 3 commits into from
Jan 9, 2019
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
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
"lodash.isequal": "^4.5.0",
"moment-mini": "^2.22.1",
"rxjs": "^6.3.3",
"slickgrid": "~2.3.23",
"slickgrid": "github:6pac/SlickGrid",
"text-encoding-utf-8": "^1.0.2",
"tslib": "^1.9.3",
"vinyl-paths": "^2.1.0"
Expand All @@ -95,6 +95,7 @@
"@types/moment": "^2.13.0",
"@types/node": "^10.12.15",
"@types/text-encoding-utf-8": "^1.0.1",
"bootstrap": "3.4.0",
"codelyzer": "~4.5.0",
"copyfiles": "^2.1.0",
"cross-env": "^5.2.0",
Expand Down
2 changes: 2 additions & 0 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { GridColspanComponent } from './examples/grid-colspan.component';
import { GridDraggableGroupingComponent } from './examples/grid-draggrouping.component';
import { GridEditorComponent } from './examples/grid-editor.component';
import { GridFormatterComponent } from './examples/grid-formatter.component';
import { GridFrozenComponent } from './examples/grid-frozen.component';
import { GridGroupingComponent } from './examples/grid-grouping.component';
import { GridHeaderButtonComponent } from './examples/grid-headerbutton.component';
import { GridHeaderMenuComponent } from './examples/grid-headermenu.component';
Expand All @@ -30,6 +31,7 @@ const routes: Routes = [
{ path: 'colspan', component: GridColspanComponent },
{ path: 'editor', component: GridEditorComponent },
{ path: 'formatter', component: GridFormatterComponent },
{ path: 'frozen', component: GridFrozenComponent },
{ path: 'headerbutton', component: GridHeaderButtonComponent },
{ path: 'headermenu', component: GridHeaderMenuComponent },
{ path: 'gridgraphql', component: GridGraphqlComponent },
Expand Down
3 changes: 3 additions & 0 deletions src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@
<li routerLinkActive="active">
<a [routerLink]="['/draggrouping']">19- Draggable Grouping</a>
</li>
<li routerLinkActive="active">
<a [routerLink]="['/frozen']">20- Pinned Columns/Rows</a>
</li>
</ul>
</div>
</section>
Expand Down
2 changes: 2 additions & 0 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { GridColspanComponent } from './examples/grid-colspan.component';
import { GridDraggableGroupingComponent } from './examples/grid-draggrouping.component';
import { GridEditorComponent } from './examples/grid-editor.component';
import { GridFormatterComponent } from './examples/grid-formatter.component';
import { GridFrozenComponent } from './examples/grid-frozen.component';
import { GridGraphqlComponent } from './examples/grid-graphql.component';
import { GridGroupingComponent } from './examples/grid-grouping.component';
import { GridHeaderButtonComponent } from './examples/grid-headerbutton.component';
Expand Down Expand Up @@ -71,6 +72,7 @@ export function appInitializerFactory(translate: TranslateService, injector: Inj
GridDraggableGroupingComponent,
GridEditorComponent,
GridFormatterComponent,
GridFrozenComponent,
GridGraphqlComponent,
GridGroupingComponent,
GridHeaderButtonComponent,
Expand Down
41 changes: 41 additions & 0 deletions src/app/examples/grid-frozen.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<div class="container">
<h2>{{title}}</h2>
<div class="subtitle" [innerHTML]="subTitle"></div>

<br>

<div class="row col-sm-12">
<span>
<label for="">Pinned Rows: </label>
<input type="number" [(ngModel)]="frozenRowCount">
<button class="btn btn-default btn-xs" (click)="changeFrozenRowCount()">
Set
</button>
</span>
<span style="margin-left: 10px">
<label for="">Pinned Columns: </label>
<input type="number" [(ngModel)]="frozenColumnCount">
<button class="btn btn-default btn-xs" (click)="changeFrozenColumnCount()">
Set
</button>
</span>
<span style="margin-left: 15px">
<button class="btn btn-default btn-sm" (click)="toggleFrozenBottomRows()">
<i class="fa fa-random fa-lg"></i> Toggle Pinned Rows
</button>
<span style="font-weight: bold;">: {{ isFrozenBottom ? 'Bottom' : 'Top' }}</span>
</span>
</div>

<div class="col-sm-12">
<hr>
</div>

<angular-slickgrid gridId="grid20"
gridWidth="875"
[columnDefinitions]="columnDefinitions"
[gridOptions]="gridOptions"
[dataset]="dataset"
(onAngularGridCreated)="angularGridReady($event)">
</angular-slickgrid>
</div>
11 changes: 11 additions & 0 deletions src/app/examples/grid-frozen.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/** You can change the pinned/frozen border styling through this css override */

.slick-row .slick-cell.frozen:last-child,
.slick-headerrow-column.frozen:last-child,
.slick-footerrow-column.frozen:last-child {
border-right: 1px solid #969696 !important;
}

.slick-pane-bottom {
border-top: 1px solid #969696 !important;
}
190 changes: 190 additions & 0 deletions src/app/examples/grid-frozen.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { AngularGridInstance, Column, FieldType, Formatters, Filters, GridOption } from './../modules/angular-slickgrid';

@Component({
templateUrl: './grid-frozen.component.html',
styleUrls: ['./grid-frozen.component.scss'],
encapsulation: ViewEncapsulation.None,
})
export class GridFrozenComponent implements OnInit {
title = 'Example 20: Pinned (frozen) Columns/Rows';
subTitle = `
This example demonstrates the use of Pinned (aka frozen) Columns and/or Rows<br/>
<ul>
<li>Option to pin any number of columns (left only) or rows</li>
<li>Option to pin the rows at the bottom instead of the top (default)</li>
<li>You can also dynamically any of these options, through SlickGrid "setOptions()"</li>
<li>Possibility to change the styling of the line border between pinned columns/rows</li>
</ul>
`;

angularGrid: AngularGridInstance;
columnDefinitions: Column[];
gridOptions: GridOption;
dataset: any[];
frozenColumnCount = 2;
frozenRowCount = 3;
isFrozenBottom = false;
gridObj: any;

ngOnInit(): void {
this.prepareDataGrid();
}

angularGridReady(angularGrid: any) {
this.angularGrid = angularGrid;
this.gridObj = angularGrid.slickGrid;
}

prepareDataGrid() {
this.columnDefinitions = [
{
id: 'sel', name: '#', field: 'id',
minWidth: 40, width: 40, maxWidth: 40,
cannotTriggerInsert: true,
resizable: false,
unselectable: true,
},
{
id: 'title', name: 'Title', field: 'title',
minWidth: 100, width: 120,
filterable: true,
sortable: true
},
{
id: 'duration', name: 'Duration', field: 'duration',
minWidth: 100, width: 120,
filterable: true,
sortable: true
},
{
id: 'percentComplete', name: '% Complete', field: 'percentComplete',
resizable: false,
minWidth: 130, width: 140,
formatter: Formatters.percentCompleteBar,
type: FieldType.number,
filterable: true,
filter: { model: Filters.slider, operator: '>=' },
sortable: true
},
{
id: 'start', name: 'Start', field: 'start',
minWidth: 100, width: 120,
filterable: true,
sortable: true
},
{
id: 'finish', name: 'Finish', field: 'finish',
minWidth: 100, width: 120,
filterable: true,
sortable: true
},
{
id: 'effortDriven', name: 'Effort Driven', field: 'effortDriven',
minWidth: 100, width: 120,
formatter: Formatters.checkmark,
filterable: true,
filter: {
collection: [{ value: '', label: '' }, { value: true, label: 'True' }, { value: false, label: 'False' }],
model: Filters.singleSelect
},
sortable: true
},
{
id: 'title1', name: 'Title1', field: 'title1',
minWidth: 100, width: 120,
filterable: true,
sortable: true
},
{
id: 'title2', name: 'Title2', field: 'title2',
minWidth: 100, width: 120,
filterable: true,
sortable: true
},
{
id: 'title3', name: 'Title3', field: 'title3',
minWidth: 100, width: 120,
filterable: true,
sortable: true
},
{
id: 'title4', name: 'Title4', field: 'title4',
minWidth: 100, width: 120,
filterable: true,
sortable: true
}
];

this.gridOptions = {
enableAutoResize: true,
autoResize: {
containerId: 'demo-container',
sidePadding: 15
},
alwaysShowVerticalScroll: false, // disable scroll since we don't want it to show on the left pinned columns
enableCellNavigation: true,
enableFiltering: true,
asyncEditorLoading: true,
forceFitColumns: false,
autoEdit: false,
frozenColumn: this.frozenColumnCount,
frozenRow: this.frozenRowCount,
// frozenBottom: true, // if you want to freeze the bottom instead of the top, you can enable this property
showHeaderRow: true,
syncColumnCellResize: false,
};

// mock a dataset
this.dataset = this.getData();
}

getData() {
// Set up some test columns.
const mockDataset = [];
for (let i = 0; i < 500; i++) {
mockDataset[i] = {
id: i,
title: 'Task ' + i,
duration: Math.round(Math.random() * 25) + ' days',
percentComplete: Math.round(Math.random() * 100),
start: '01/01/2009',
finish: '01/05/2009',
effortDriven: (i % 5 === 0),
title1: Math.round(Math.random() * 25),
title2: Math.round(Math.random() * 25),
title3: Math.round(Math.random() * 25),
title4: Math.round(Math.random() * 25),
};
}
return mockDataset;
}

/** change dynamically, through slickgrid "setOptions()" the number of pinned columns */
changeFrozenColumnCount() {
if (this.gridObj && this.gridObj.setOptions) {
this.gridObj.setOptions({
frozenColumn: this.frozenColumnCount
});
}
}

/** change dynamically, through slickgrid "setOptions()" the number of pinned rows */
changeFrozenRowCount() {
if (this.gridObj && this.gridObj.setOptions) {
this.gridObj.setOptions({
frozenRow: this.frozenRowCount
});
}
}

/** toggle dynamically, through slickgrid "setOptions()" the top/bottom pinned location */
toggleFrozenBottomRows() {
if (this.gridObj && this.gridObj.setOptions) {
this.gridObj.setOptions({
frozenBottom: !this.isFrozenBottom
});
this.isFrozenBottom = !this.isFrozenBottom; // toggle the variable
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,12 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn
this.dataView.beginUpdate();
this.dataView.setItems(this._dataset, this.gridOptions.datasetIdPropertyName);
this.dataView.endUpdate();

// if you don't want the items that are not visible (due to being filtered out
// or being on a different page) to stay selected, pass 'false' to the second arg
if (this.gridOptions && this.gridOptions.dataView && this.gridOptions.dataView.hasOwnProperty('syncGridSelection')) {
this.dataView.syncGridSelection(this.grid, this.gridOptions.dataView.syncGridSelection);
}
}

// user might want to hide the header row on page load but still have `enableFiltering: true`
Expand Down
3 changes: 3 additions & 0 deletions src/app/modules/angular-slickgrid/models/column.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@ export interface Column {
/** What is the Field Type, this can be used in the Formatters/Editors/... */
type?: FieldType;

/** Defaults to false, when set to True will lead to the column being unselected in the UI */
unselectable?: boolean;

/** Editor Validator */
validator?: EditorValidator;

Expand Down
20 changes: 20 additions & 0 deletions src/app/modules/angular-slickgrid/models/gridOption.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@ export interface GridOption {
/** Unique property name on the dataset used by Slick.Data.DataView */
datasetIdPropertyName?: string;

dataView?: {
/**
* if you don't want the items that are not visible (due to being filtered out
* or being on a different page) to stay selected, the set this property as 'false'
*/
syncGridSelection?: boolean;
};

/** Default column width, is set to 80 when null */
defaultColumnWidth?: number;

Expand Down Expand Up @@ -212,6 +220,15 @@ export interface GridOption {
/** Formatter classes factory */
formatterFactory?: any;

/** Defaults to false, do we want to freeze (pin) the bottom portion instead of the top */
frozenBottom?: boolean;

/** Number of column(s) to freeze (pin) in the grid */
frozenColumn?: number;

/** Number of row(s) to freeze (pin) in the grid */
frozenRow?: number;

/** Defaults to false, which leads to have row with full width */
fullWidthRows?: boolean;

Expand Down Expand Up @@ -317,6 +334,9 @@ export interface GridOption {
*/
suppressActiveCellChangeOnEdit?: boolean;

/** Defaults to false, when set to True will sync the column cell resize & apply the column width */
syncColumnCellResize?: boolean;

/** What is the top panel height in pixels (only type the number) */
topPanelHeight?: number;

Expand Down
Loading