Angular Grid Row Pinning
One or multiple rows can be pinned to the top or bottom of the Angular UI Grid. Row Pinning in Ignite UI for Angular allows end-users to pin rows in a particular order, duplicating them in a special area that is always visible even when they scroll the Grid vertically. The Material UI Grid has a built-in row pinning UI, which is enabled by initializing an igxActionStrip
component in the context of Grid. In addition, you can define custom UI and change the pin state of the rows via the Row Pinning API.
Angular Grid Row Pinning Example
Row Pinning UI
The built-in row pinning UI is enabled by adding an igxActionStrip
component with the GridPinningActions
component. The action strip is automatically shown when hovering a row and will display a pin or unpin button icon based on the state of the row it is shown for. An additional action allowing to scroll the copy of the pinned row into view is shown for each pinned row as well.
<igx-grid [data]="data" [autoGenerate]="false">
<igx-column *ngFor="let c of columns" [field]="c.field" [header]="c.field">
</igx-column>
<igx-action-strip #actionStrip>
<igx-grid-pinning-actions></igx-grid-pinning-actions>
<igx-grid-editing-actions></igx-grid-editing-actions>
</igx-action-strip>
</igx-grid>
Row Pinning API
Row pinning is controlled through the pinned
input of the row
. Pinned rows are rendered at the top of the Grid by default and stay fixed through vertical scrolling of the unpinned rows in the Grid body.
this.grid.getRowByIndex(0).pinned = true;
You may also use the Grid's pinRow
or unpinRow
methods of the IgxGridComponent
to pin or unpin records by their ID:
this.grid.pinRow('ALFKI');
this.grid.unpinRow('ALFKI');
Note that the row ID is the primary key value, defined by the primaryKey
of the grid, or the record instance itself. Both methods return a boolean value indicating whether their respective operation is successful or not. Usually the reason they fail is that the row is already in the desired state.
A row is pinned below the last pinned row. Changing the order of the pinned rows can be done by subscribing to the rowPinning
event and changing the insertAtIndex
property of the event arguments to the desired position index.
<igx-grid #grid1 [data]="data" [autoGenerate]="true" (rowPinning)="rowPinning($event)">
</igx-grid>
public rowPinning(event) {
event.insertAtIndex = 0;
}
Pinning Position
You can change the row pinning position via the pinning
configuration option. It allows you to set the pin area position to either Top or Bottom.
When set to Bottom pinned rows are rendered at the bottom of the grid, after the unpinned rows. Unpinned rows can be scrolled vertically, while the pinned rows remain fixed at the bottom.
<igx-grid [data]="data" [autoGenerate]="true" [pinning]="pinningConfig"></igx-grid>
public pinningConfig: IPinningConfig = { rows: RowPinningPosition.Bottom };
Custom Row Pinning UI
You can define your custom UI and change the pin state of the rows via the related API.
Via extra column with icon
Let's say that instead of an action strip you would like to show a pin icon in every row allowing the end-user to click and change a particular row's pin state. This can be done by adding an extra column with a cell template containing the custom icon.
<igx-grid [data]="data" [primaryKey]="'ID'" [autoGenerate]="false">
<igx-column width="70px">
<ng-template igxCell let-cell="cell" let-val>
<igx-icon class="pin-icon" (mousedown)="togglePinning(cell.row, $event)">
{{cell.row.pinned ? 'lock' : 'lock_open'}}
</igx-icon>
</ng-template>
</igx-column>
<igx-column *ngFor="let c of columns" [field]="c.field" [header]="c.field">
</igx-column>
</igx-grid>
On click of the custom icon the pin state of the related row can be changed using the row's API methods.
public togglePinning(row: IgxGridRow, event) {
event.preventDefault();
if (row.pinned) {
row.unpin();
} else {
row.pin();
}
}
Demo
Via row drag
Let's say that you want to be able to directly drag and drop a row between the pinned and unpinned rows to change its pin state. This can be achieved by enabling the row drag feature and pinning/unpinning the rows via the API on drop.
First, the grid should be marked as a drop area using the igxDrop
directive and the row drag functionality should be enabled via the rowDraggable
option.
<igx-grid [data]="data" [autoGenerate]="true" [rowDraggable]="true"
[primaryKey]="'ID'" igxDrop (dropped)="onDropAllowed($event)">
</igx-grid>
Then the dropped
event can be used to handle the reorder and pin/unpin logic.
public onDropAllowed(args) {
const event = args.originalEvent;
let currRowPinnedIndex;
const currRowIndex = this.getCurrentRowIndex(this.grid.rowList.toArray(),
{ x: event.clientX, y: event.clientY });
if (currRowIndex === -1) { return; }
const currRowID = this.getCurrentRowID(this.grid.rowList.toArray(),
{ x: event.clientX, y: event.clientY });
const currentRow = this.grid.rowList.toArray().find((r) => r.rowID === currRowID);
if (currentRow.pinned) {
currRowPinnedIndex = this.grid.pinnedRows.indexOf(this.grid.pinnedRows.find((r) => r.rowID === currRowID));
}
// remove the row that was dragged and place it onto its new location
this.grid.deleteRow(args.dragData.key);
this.data.splice(currRowIndex, 0, args.dragData.data);
if (currentRow.pinned && !args.dragData.pinned) {
this.grid.pinRow(args.dragData.key, currRowPinnedIndex);
} else if (!currentRow.pinned && args.dragData.pinned) {
this.grid.unpinRow(args.dragData.key);
} else if (currentRow.pinned && args.dragData.pinned) {
this.grid.unpinRow(args.dragData.key);
this.grid.pinRow(args.dragData.key, currRowPinnedIndex);
}
}
This would allow reordering the rows and moving them between the pinned and unpinned row collections.
Demo
Row Pinning Limitations
- Only records that exist in the data source can be pinned.
- The row pinning state is not exported to excel. The grid is exported as if no row pinning is applied.
- Because of how pinned rows are stored internally so that they may appear both in the pinned and unpinned areas of the grid, row pinning is not supported when records in the grid are fetched from a remote endpoint on demand (remote virtualization).
- The copies of pinned rows in the scrollable area of the grid are an integral part of how other grid features achieve their functionality in the presence of pinned rows and therefore their creation cannot be disabled nor can they be removed.
- As Row Selection works entirely with row Ids, selecting pinned rows selects their copies as well (and vise versa). Additionally, range selection (e.g. using Shift + click) within the pinned area works the same way as selecting a range of rows within the scrollable area. The resulting selection includes all rows in between even if they are not currently pinned. Getting the selected rows through the API only returns a single instance of each selected record.
- When the grid has no
primaryKey
set and remote data scenarios are enabled (when paging, sorting, filtering, scrolling trigger requests to a remote server to retrieve the data to be displayed in the grid), a row will lose the following state after a data request completes:- Row Selection
- Row Expand/collapse
- Row Editing
- Row Pinning
Styling
The IgxGrid allows styling through the Ignite UI for Angular Theme Library. The Grid's theme exposes a wide variety of properties, which allow the customization of all the features of the Grid.
Below, we are going through the steps of customizing the Grid's row pinning styling.
Importing the Styling Library
To begin the customization of the row pinning feature, you need to import the index
file, where all styling functions and mixins are located.
@use "igniteui-angular/theming" as *;
// IMPORTANT: Prior to Ignite UI for Angular version 13 use:
// @import '~igniteui-angular/lib/core/styles/themes/index';
Defining a Theme
Next, create a new theme, that extends the grid-theme
and accepts the parameters, required to customize the row pinning feature as desired.
$custom-grid-theme: grid-theme(
/* Pinning properties that affect styling */
$pinned-border-width: 5px,
$pinned-border-style: double,
$pinned-border-color: #FFCD0F,
$cell-active-border-color: #FFCD0F
/* add other features properties here... */
);
Using CSS variables
The last step is to pass the custom grid theme:
@include css-vars($custom-grid-theme);
Using mixins
In order to style components for Internet Explorer 11, you have to use different approach, since it doesn't support CSS variables.
If the component is using an Emulated
ViewEncapsulation, it is necessary to penetrate
this encapsulation using ::ng-deep
. However, in order to prevent the custom theme to leak to other components, be sure to include the :host
selector before ::ng-deep
:
:host {
::ng-deep {
// Pass the custom grid theme to the `igx-grid` mixin
@include grid($custom-grid-theme);
}
}
Demo
Note
The sample will not be affected by the selected global theme from Change Theme
.
API References
Additional Resources
- Grid overview
- Virtualization and Performance
- Paging
- Filtering
- Sorting
- Summaries
- Column Moving
- Column Resizing
- Selection