Skip to content

Commit 1b9d9e2

Browse files
authored
Merge pull request #16132 from IgniteUI/mkirova/col-pin-directions
Column pinning - both sides.
2 parents 8de2a92 + 3a97bb2 commit 1b9d9e2

37 files changed

+700
-196
lines changed

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,26 @@ All notable changes for each version of this project will be documented in this
1010
```ts
1111
this.carousel.select(2, Direction.NEXT);
1212
```
13+
- `IgxGrid`, `IgxTreeGrid`, `IgxHierarchicalGrid`
14+
- Added ability to pin individual columns to a specific side (start or end of the grid), so that you can now have pinning from both sides. This can be done either declaratively by setting the `pinningPosition` property on the column:
15+
16+
```html
17+
<igx-column [field]="'Col1'" [pinned]='true' [pinningPosition]='pinningPosition'>
18+
</igx-column>
19+
```
20+
21+
```ts
22+
public pinningPosition = ColumnPinningPosition.End;
23+
```
24+
25+
Or with the API, via optional parameter:
26+
27+
```ts
28+
grid.pinColumn('Col1', 0, ColumnPinningPosition.End);
29+
grid.pinColumn('Col2', 0, ColumnPinningPosition.Start);
30+
```
31+
32+
If property `pinningPosition` is not set on a column, the column will default to the position specified on the grid's `pinning` options for `columns`.
1333

1434
- `IgxDateRangePicker`
1535
- Added new properties:

projects/igniteui-angular-elements/src/analyzer/elements.config.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,8 @@ export var registerConfig = [
274274
{ name: "defaultHeaderGroupMinWidth" },
275275
{ name: "columns" },
276276
{ name: "pinnedColumns" },
277+
{ name: "pinnedStartColumns" },
278+
{ name: "pinnedEndColumns" },
277279
{ name: "pinnedRows" },
278280
{ name: "unpinnedColumns" },
279281
{ name: "visibleColumns" },
@@ -327,7 +329,8 @@ export var registerConfig = [
327329
"findPrev",
328330
"refreshSearch",
329331
"clearSearch",
330-
"getPinnedWidth",
332+
"getPinnedStartWidth",
333+
"getPinnedEndWidth",
331334
"selectRows",
332335
"deselectRows",
333336
"selectAllRows",
@@ -568,6 +571,8 @@ export var registerConfig = [
568571
{ name: "defaultHeaderGroupMinWidth" },
569572
{ name: "columns" },
570573
{ name: "pinnedColumns" },
574+
{ name: "pinnedStartColumns" },
575+
{ name: "pinnedEndColumns" },
571576
{ name: "pinnedRows" },
572577
{ name: "unpinnedColumns" },
573578
{ name: "visibleColumns" },
@@ -613,7 +618,8 @@ export var registerConfig = [
613618
"findPrev",
614619
"refreshSearch",
615620
"clearSearch",
616-
"getPinnedWidth",
621+
"getPinnedStartWidth",
622+
"getPinnedEndWidth",
617623
"selectRows",
618624
"deselectRows",
619625
"selectAllRows",
@@ -748,6 +754,8 @@ export var registerConfig = [
748754
{ name: "defaultRowHeight" },
749755
{ name: "defaultHeaderGroupMinWidth" },
750756
{ name: "columns" },
757+
{ name: "pinnedStartColumns" },
758+
{ name: "pinnedEndColumns" },
751759
{ name: "visibleColumns" },
752760
{ name: "dataView" },
753761
],
@@ -780,6 +788,7 @@ export var registerConfig = [
780788
"clearFilter",
781789
"clearSort",
782790
"reflow",
791+
"getPinnedEndWidth",
783792
"selectRows",
784793
"deselectRows",
785794
"selectAllRows",
@@ -872,6 +881,8 @@ export var registerConfig = [
872881
{ name: "defaultRowHeight" },
873882
{ name: "defaultHeaderGroupMinWidth" },
874883
{ name: "columns" },
884+
{ name: "pinnedStartColumns" },
885+
{ name: "pinnedEndColumns" },
875886
{ name: "pinnedRows" },
876887
],
877888
methods: [
@@ -908,7 +919,8 @@ export var registerConfig = [
908919
"findPrev",
909920
"refreshSearch",
910921
"clearSearch",
911-
"getPinnedWidth",
922+
"getPinnedStartWidth",
923+
"getPinnedEndWidth",
912924
"selectRows",
913925
"deselectRows",
914926
"selectAllRows",
@@ -1022,6 +1034,8 @@ export var registerConfig = [
10221034
{ name: "defaultHeaderGroupMinWidth" },
10231035
{ name: "columns" },
10241036
{ name: "pinnedColumns" },
1037+
{ name: "pinnedStartColumns" },
1038+
{ name: "pinnedEndColumns" },
10251039
{ name: "pinnedRows" },
10261040
{ name: "unpinnedColumns" },
10271041
{ name: "visibleColumns" },
@@ -1069,7 +1083,8 @@ export var registerConfig = [
10691083
"findPrev",
10701084
"refreshSearch",
10711085
"clearSearch",
1072-
"getPinnedWidth",
1086+
"getPinnedStartWidth",
1087+
"getPinnedEndWidth",
10731088
"selectRows",
10741089
"deselectRows",
10751090
"selectAllRows",

projects/igniteui-angular/src/lib/grids/columns/column-layout.component.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,15 +82,10 @@ export class IgxColumnLayoutComponent extends IgxColumnGroupComponent implements
8282
}
8383

8484
const unpinnedColumns = this.grid.unpinnedColumns.filter(c => c.columnLayout && !c.hidden);
85-
const pinnedColumns = this.grid.pinnedColumns.filter(c => c.columnLayout && !c.hidden);
86-
let vIndex = -1;
87-
88-
if (!this.pinned) {
89-
const indexInCollection = unpinnedColumns.indexOf(this);
90-
vIndex = indexInCollection === -1 ? -1 : pinnedColumns.length + indexInCollection;
91-
} else {
92-
vIndex = pinnedColumns.indexOf(this);
93-
}
85+
const pinnedStart = this.grid.pinnedStartColumns.filter(c => c.columnLayout && !c.hidden);
86+
const pinnedEndColumns = this.grid.pinnedEndColumns.filter(c => c.columnLayout && !c.hidden);
87+
const ordered = pinnedStart.concat(unpinnedColumns, pinnedEndColumns);
88+
let vIndex = ordered.indexOf(this);
9489
this._vIndex = vIndex;
9590
return vIndex;
9691
}
@@ -158,7 +153,7 @@ export class IgxColumnLayoutComponent extends IgxColumnGroupComponent implements
158153
public override populateVisibleIndexes() {
159154
this.childrenVisibleIndexes = [];
160155
const columns = this.grid?.pinnedColumns && this.grid?.unpinnedColumns
161-
? this.grid.pinnedColumns.concat(this.grid.unpinnedColumns)
156+
? this.grid.pinnedStartColumns.concat(this.grid.unpinnedColumns, this.grid.pinnedEndColumns)
162157
: [];
163158
const orderedCols = columns
164159
.filter(x => !x.columnGroup && !x.hidden)

projects/igniteui-angular/src/lib/grids/columns/column.component.ts

Lines changed: 73 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ import { IColumnVisibilityChangingEventArgs, IPinColumnCancellableEventArgs, IPi
5656
import { isConstructor, PlatformUtil } from '../../core/utils';
5757
import { IgxGridCell } from '../grid-public-cell';
5858
import { NG_VALIDATORS, Validator } from '@angular/forms';
59-
import { Size } from '../common/enums';
59+
import { ColumnPinningPosition, Size } from '../common/enums';
6060
import { ExpressionsTreeUtil } from '../../data-operations/expressions-tree-util';
6161

6262
const DEFAULT_DATE_FORMAT = 'mediumDate';
@@ -1041,6 +1041,28 @@ export class IgxColumnComponent implements AfterContentInit, OnDestroy, ColumnTy
10411041
return (this.grid as any)._columns.indexOf(this);
10421042
}
10431043

1044+
/**
1045+
* Gets the pinning position of the column.
1046+
* ```typescript
1047+
* let pinningPosition = this.column.pinningPosition;
1048+
*/
1049+
@WatchColumnChanges()
1050+
@Input()
1051+
public get pinningPosition(): ColumnPinningPosition {
1052+
const userSet = this._pinningPosition !== null && this._pinningPosition !== undefined;
1053+
return userSet ? this._pinningPosition : this.grid.pinning.columns;
1054+
}
1055+
1056+
/**
1057+
* Sets the pinning position of the column.
1058+
*```html
1059+
* <igx-column [pinningPosition]="1"></igx-column>
1060+
* ```
1061+
*/
1062+
public set pinningPosition(value: ColumnPinningPosition) {
1063+
this._pinningPosition = value;
1064+
}
1065+
10441066
/**
10451067
* Gets whether the column is `pinned`.
10461068
* ```typescript
@@ -1487,7 +1509,8 @@ export class IgxColumnComponent implements AfterContentInit, OnDestroy, ColumnTy
14871509
return this._vIndex;
14881510
}
14891511
const unpinnedColumns = this.grid.unpinnedColumns.filter(c => !c.columnGroup);
1490-
const pinnedColumns = this.grid.pinnedColumns.filter(c => !c.columnGroup);
1512+
const pinnedStartColumns = this.grid.pinnedStartColumns.filter(c => !c.columnGroup);
1513+
const pinnedEndColumns = this.grid.pinnedEndColumns.filter(c => !c.columnGroup);
14911514

14921515
let col = this;
14931516
let vIndex = -1;
@@ -1502,15 +1525,13 @@ export class IgxColumnComponent implements AfterContentInit, OnDestroy, ColumnTy
15021525
if (!this.pinned) {
15031526
const indexInCollection = unpinnedColumns.indexOf(col);
15041527
vIndex = indexInCollection === -1 ?
1505-
-1 :
1506-
(this.grid.isPinningToStart ?
1507-
pinnedColumns.length + indexInCollection :
1508-
indexInCollection);
1528+
-1 : pinnedStartColumns.length + indexInCollection;
15091529
} else {
1510-
const indexInCollection = pinnedColumns.indexOf(col);
1511-
vIndex = this.grid.isPinningToStart ?
1530+
const indexInCollection = this.pinningPosition === ColumnPinningPosition.Start ?
1531+
pinnedStartColumns.indexOf(col) : pinnedEndColumns.indexOf(col);
1532+
vIndex = this.pinningPosition === ColumnPinningPosition.Start ?
15121533
indexInCollection :
1513-
unpinnedColumns.length + indexInCollection;
1534+
pinnedStartColumns.length + unpinnedColumns.length + indexInCollection;
15141535
}
15151536
this._vIndex = vIndex;
15161537
return vIndex;
@@ -1588,20 +1609,20 @@ export class IgxColumnComponent implements AfterContentInit, OnDestroy, ColumnTy
15881609

15891610
/** @hidden @internal **/
15901611
public get isLastPinned(): boolean {
1591-
return this.grid.isPinningToStart &&
1592-
this.grid.pinnedColumns[this.grid.pinnedColumns.length - 1] === this;
1612+
return this.pinningPosition === ColumnPinningPosition.Start &&
1613+
this.grid.pinnedStartColumns[this.grid.pinnedStartColumns.length - 1] === this;
15931614
}
15941615

15951616
/** @hidden @internal **/
15961617
public get isFirstPinned(): boolean {
1597-
const pinnedCols = this.grid.pinnedColumns.filter(x => !x.columnGroup);
1598-
return !this.grid.isPinningToStart && pinnedCols[0] === this;
1618+
const pinnedCols = this.grid.pinnedEndColumns.filter(x => !x.columnGroup);
1619+
return this.pinningPosition === ColumnPinningPosition.End && pinnedCols[0] === this;
15991620
}
16001621

16011622
/** @hidden @internal **/
16021623
public get rightPinnedOffset(): string {
1603-
return this.pinned && !this.grid.isPinningToStart ?
1604-
- this.grid.pinnedWidth - this.grid.headerFeaturesWidth + 'px' :
1624+
return this.pinned && this.pinningPosition === ColumnPinningPosition.End ?
1625+
- this.grid.pinnedEndWidth - this.grid.pinnedStartWidth + 'px' :
16051626
null;
16061627
}
16071628

@@ -1794,6 +1815,7 @@ export class IgxColumnComponent implements AfterContentInit, OnDestroy, ColumnTy
17941815
protected _applySelectableClass = false;
17951816

17961817
protected _vIndex = NaN;
1818+
protected _pinningPosition = null;
17971819
/**
17981820
* @hidden
17991821
*/
@@ -2187,20 +2209,19 @@ export class IgxColumnComponent implements AfterContentInit, OnDestroy, ColumnTy
21872209
}
21882210

21892211
/**
2190-
* Pins the column at the provided index in the pinned area.
2212+
* Pins the column in the specified position at the provided index in that pinned area.
21912213
* Defaults to index `0` if not provided, or to the initial index in the pinned area.
21922214
* Returns `true` if the column is successfully pinned. Returns `false` if the column cannot be pinned.
21932215
* Column cannot be pinned if:
21942216
* - Is already pinned
21952217
* - index argument is out of range
2196-
* - The pinned area exceeds 80% of the grid width
21972218
* ```typescript
21982219
* let success = this.column.pin();
21992220
* ```
22002221
*
22012222
* @memberof IgxColumnComponent
22022223
*/
2203-
public pin(index?: number): boolean {
2224+
public pin(index?: number, pinningPosition?: ColumnPinningPosition): boolean {
22042225
// TODO: Probably should the return type of the old functions
22052226
// should be moved as a event parameter.
22062227
const grid = (this.grid as any);
@@ -2209,19 +2230,23 @@ export class IgxColumnComponent implements AfterContentInit, OnDestroy, ColumnTy
22092230
}
22102231

22112232
if (this.parent && !this.parent.pinned) {
2212-
return this.topLevelParent.pin(index);
2213-
}
2214-
2215-
const hasIndex = index !== undefined;
2216-
if (hasIndex && (index < 0 || index > grid.pinnedColumns.length)) {
2233+
return this.topLevelParent.pin(index, pinningPosition);
2234+
}
2235+
const targetPinPosition = pinningPosition !== null && pinningPosition !== undefined ? pinningPosition : this.pinningPosition;
2236+
const pinningVisibleCollection = targetPinPosition === ColumnPinningPosition.Start ?
2237+
grid.pinnedStartColumns : grid.pinnedEndColumns;
2238+
const pinningCollection = targetPinPosition === ColumnPinningPosition.Start ?
2239+
grid._pinnedStartColumns : grid._pinnedEndColumns;
2240+
const hasIndex = index !== undefined && index !== null;
2241+
if (hasIndex && (index < 0 || index > pinningVisibleCollection.length)) {
22172242
return false;
22182243
}
22192244

22202245
if (!this.parent && !this.pinnable) {
22212246
return false;
22222247
}
22232248

2224-
const rootPinnedCols = grid._pinnedColumns.filter((c) => c.level === 0);
2249+
const rootPinnedCols = pinningCollection.filter((c) => c.level === 0);
22252250
index = hasIndex ? index : rootPinnedCols.length;
22262251
const args: IPinColumnCancellableEventArgs = { column: this, insertAtIndex: index, isPinned: false, cancel: false };
22272252
this.grid.columnPin.emit(args);
@@ -2233,14 +2258,20 @@ export class IgxColumnComponent implements AfterContentInit, OnDestroy, ColumnTy
22332258
this.grid.crudService.endEdit(false);
22342259

22352260
this._pinned = true;
2261+
if (pinningPosition !== null && pinningPosition !== undefined) {
2262+
// if user has set some position in the params, overwrite the column's position.
2263+
this._pinningPosition = pinningPosition;
2264+
}
2265+
22362266
this.pinnedChange.emit(this._pinned);
22372267
// it is possible that index is the last position, so will need to find target column by [index-1]
2238-
const targetColumn = args.insertAtIndex === grid._pinnedColumns.length ?
2239-
grid._pinnedColumns[args.insertAtIndex - 1] : grid._pinnedColumns[args.insertAtIndex];
2268+
const targetColumn = args.insertAtIndex === pinningCollection.length ?
2269+
pinningCollection[args.insertAtIndex - 1] : pinningCollection[args.insertAtIndex];
22402270

2241-
if (grid._pinnedColumns.indexOf(this) === -1) {
2271+
if (pinningCollection.indexOf(this) === -1) {
22422272
if (!grid.hasColumnGroups) {
2243-
grid._pinnedColumns.splice(args.insertAtIndex, 0, this);
2273+
pinningCollection.splice(args.insertAtIndex, 0, this);
2274+
grid._pinnedColumns = grid._pinnedStartColumns.concat(grid._pinnedEndColumns);
22442275
} else {
22452276
// insert based only on root collection
22462277
if (this.level === 0) {
@@ -2254,6 +2285,11 @@ export class IgxColumnComponent implements AfterContentInit, OnDestroy, ColumnTy
22542285
allPinned = allPinned.concat(group.allChildren);
22552286
});
22562287
grid._pinnedColumns = allPinned;
2288+
if (this.pinningPosition === ColumnPinningPosition.Start) {
2289+
grid._pinnedStartColumns = allPinned;
2290+
} else {
2291+
grid._pinnedEndColumns = allPinned;
2292+
}
22572293
}
22582294

22592295
if (grid._unpinnedColumns.indexOf(this) !== -1) {
@@ -2263,12 +2299,12 @@ export class IgxColumnComponent implements AfterContentInit, OnDestroy, ColumnTy
22632299
}
22642300

22652301
if (hasIndex) {
2266-
index === grid._pinnedColumns.length - 1 ?
2302+
index === pinningCollection.length - 1 ?
22672303
grid._moveColumns(this, targetColumn, DropPosition.AfterDropTarget) : grid._moveColumns(this, targetColumn, DropPosition.BeforeDropTarget);
22682304
}
22692305

22702306
if (this.columnGroup) {
2271-
this.allChildren.forEach(child => child.pin());
2307+
this.allChildren.forEach(child => child.pin(null, targetPinPosition));
22722308
grid.reinitPinStates();
22732309
}
22742310

@@ -2304,7 +2340,7 @@ export class IgxColumnComponent implements AfterContentInit, OnDestroy, ColumnTy
23042340
if (this.parent && this.parent.pinned) {
23052341
return this.topLevelParent.unpin(index);
23062342
}
2307-
const hasIndex = index !== undefined;
2343+
const hasIndex = index !== undefined && index !== null;
23082344
if (hasIndex && (index < 0 || index > grid._unpinnedColumns.length)) {
23092345
return false;
23102346
}
@@ -2339,6 +2375,12 @@ export class IgxColumnComponent implements AfterContentInit, OnDestroy, ColumnTy
23392375
if (grid._pinnedColumns.indexOf(this) !== -1) {
23402376
grid._pinnedColumns.splice(grid._pinnedColumns.indexOf(this), 1);
23412377
}
2378+
if (this.pinningPosition === ColumnPinningPosition.Start && grid._pinnedStartColumns.indexOf(this) !== -1) {
2379+
grid._pinnedStartColumns.splice(grid._pinnedStartColumns.indexOf(this), 1);
2380+
}
2381+
if (this.pinningPosition === ColumnPinningPosition.End && grid._pinnedEndColumns.indexOf(this) !== -1) {
2382+
grid._pinnedEndColumns.splice(grid._pinnedEndColumns.indexOf(this), 1);
2383+
}
23422384
}
23432385

23442386
if (hasIndex) {

0 commit comments

Comments
 (0)