-
Notifications
You must be signed in to change notification settings - Fork 162
Row Pinning
- Konstantin Dinev | Date:
- Radoslav Mirchev | Date: April 14, 2020
- Stefan Ivanov | Date:
Pinned Rows are visible all the time. Vertical scrolling is applied to the rest of the rows.
Version | User | Date | Notes |
---|---|---|---|
0.1 | Stamen Stoychev | February 19, 2020 | API draft |
0.2 | Stamen Stoychev | February 20, 2020 | Integration scenarios |
0.3 | Stefan Ivanov | March 2, 2020 | Finalizing user stories and UI |
0.4 | Stamen Stoychev | April 3, 2020 | Ghost rows finalization |
0.5 | Stefan Ivanov | April 6, 2020 | Updating design with action strip |
0.6 | Stamen Stoychev | April 7, 2020 | Updating Paging integration and chip |
0.7 | Stamen Stoychev | April 13, 2020 | Selection changes |
0.8 | Radoslav Mirchev | April 14, 2020 | Sign Off |
Allows a user to pin one or more rows to the top or bottom of the grid in a similar fashion to how Excel allows freezing the first few rows of a spreadsheet e.g. end-users can pin rows via the UI and developers can configure this through the API.
As an end-user:
- Story 1: I want to pin a row to the top/bottom of the grid to make it visible all the time, even when scrolling.
- Story 2: I want to unpin a row to remove it from the area at the top/bottom of the grid, which will enable the record in the scrollable grid body.
- Story 3: I want to have a clear and consistent-with-pinned-columns visual indication in order to differentiate pinned from unpinned rows.
- Story 4: I want to select several rows and pin them all at once - application scenario achievable via row selection and a grid toolbar button.
As a developer:
- Story 1: I want to programmatically pin/unpin rows by their identifier.
- Story 2: I want to have an out of the box experience for pinning rows via an action strip with predefined row pinning action.
- Programmatically pin rows ...
3.1. End-User Experience
Initially, no columns or rows are pinned and when the user hovers over any row, it shows and action strip for the row and lets the user click on the pin action.
Once a row is pinned in a similar fashion it is possible to unpin rows via an action strip shown upon hovering over the rows in the pinned area. It is also possible to jump to the original ghost row in the scrollable area of the grid. When we have top pinning we should use "vertical_align_bottom" like is shown on the image below and when we have bottom pinning we should use "vertical_align_top".
Grids pin records in a special pin area at the top or bottom of the table body. The pin area cannot be scrolled and remains visible regardless of the scroll position of the main table body.
Top-pinned rows should appear below the headers (normal headers or row filter headers) and above the scrollable grid body.
Bottom-pinned rows should appear below the scrollable grid body and above the summary rows / pager.
Pinned records are interactive but leave a copy of themselves in the main body area that receives editing updates and selection styles (when its pinned counterpart is interacted with) but cannot be edited themselves by the end-user. Their main purpose is to allow expanding/collapsing when the grid view supports hierarchy (igxHierarchicalGrid, igxTreeGrid, igxGrid with Master-detail visualization). Pinned records do not display expand/collapse icons.
-
igxTreeGrid
-
igxHierarchicalGrid
The empty space between the Pinning chip component in the ghost row and the cell text is 4px for compact grids,8px for cosy grids, and 12px for comfortable grids i.e. it varies by the grid display density.
Pinned rows display contextual UI allowing end-users to find the pinned row's disabled copy in the main table body area.
3.2. Integration with other features
-
When there is filtering applied, if a row does not match the criteria specified it will not be shown in the pinned rows area.
-
When sorting is applied on a given column, it affects the pinned and the unpinned rows independently as if they are two separate collections of records.
-
The pinned rows order should come either according to the order of pinning or via manipulating it thought the API.
-
Row pinning is also agnostic of row templates including the use of multi-row layouts.
-
Grouping is not applied on the pinned records collection, however, the pinned records ghost rows remain in their appropriate groups.
-
Paging ignores pinned rows. If the
pageSize
is e.g. 5 and there are 2 pinned records the total amount of records visible to the user for that page would be 7, the pager shows a page size of 5 and the total amount of pages is the same as though there were no pinned records (as the records are still displayed as disabled copies in the paged content). -
It should be possible to drag pinned rows e.g. from a grid to a list in a similar fashion to how the drag directive normally works.
-
Exporting to MS Excel ignores pinning and exports the grid as if no rows are pinned
An action strip provides the default UI for pinning rows because they don't own specific UI to be pinned by default. It's up to the developer to decide if the default UI for row pinning is enabled for end-users. Otherwise pinning will be exclusive to API calls.
By default, rows are always pinned one after the other (the second pinned appears under the first pinned one) regardless of the pinning position.
3.3. Developer Experience
Nothing specific is required by the developer to allow row pinning. The grid exposes API that allows pinning/unpinning a row by its id that always works. Additionally, where the row is pinned is controlled with the pinning
input with the following signature:
export interface IPinningConfig {
columns?: ColumnPinningPosition;
rows?: RowPinningPosition;
// P2
rowsUI: boolean
}
@Input()
pinning: IPinningConfig;
Where RowPinningPosition
is an enumeration with two options - RowPinningPosition.Top
(default) and RowPinningPosition.Bottom
.
Rows are pinned and unpinned using the pinRow
and unpinRow
methods respectively, exposed in grid-base.directive
therefore available for all grid variants. Similar to the column counterparts, the row directive has pin
and unpin
methods that are used under the hood, as well as pinned
getter/setter for maximum flexibility to the user. Pin method accept an optional index
parameter. Controlling the index using the other methods of pinning is done through the onRowPinning
output insertAtIndex
argument.
export interface IPinRowEventArgs extends IBaseEventArgs {
row: IgxRowDirective<T>;
insertAtIndex: number;
isPinned: boolean;
}
@Output()
public onRowPinning = new EventEmitter<IPinRowEventArgs>();
Pinned rows are rendered outside igxFor
's display container and instead use ngFor
as a structural directive. The collection passed to ngFor
contains actual record references, while the igxFor
collection includes special objects that refer to those records but can be recognized as copies for templating and functionality purposes. Not all pipes run for the pinned records collection. The list below details the exact behavior for affected features.
-
gridTransaction
- runs separately on both collections -
visibleColumns
- runs on a combined collection -
gridFiltering
- runs separately on both collections -
gridSort
- runs separately on both collections (both pinned and unpinned columns should be sorted based on the expressions) -
gridGroupBy
- runs only on the unpinned rows collection (pinned rows should not show group by rows) -
gridPaging
- runs only on the unpinned collection -
gridSummary
- global summaries run on the original data, group by ones run on the group again with the original collection -
gridDetails
- runs only on the unpinned collection. Master rows that are pinned leave ghost copies which can be expanded/collapsed.
The ghost row is a disabled copy of a pinned one that appears in its original place in the scrollable area of the grid. It may be expanded if it is part of a hierarchical structure but cannot be directly edited (it may still be selected or participate in range selection). It is decorated with disabled style and a specific template is inserted in its first data cell, regardless of whether it has user-specified template or not (similar to how expanders are added for the expand/collapse tree cells). By default this template contains a chip with the text "Pinned". The template is available for user override through the IgxPinnedIndicatorTemplateDirective
.
<ng-template igxPinnedIndicatorTemplate>
<igx-icon role="icon" fontSet="material">lock</igx-icon>
</ng-template>
As the pinned record is rendered once in the pinned area with no expander, and once in the unpinned area as a disabled row, there are specific integrations scenarios associated with the duplication of the row:
- Updating (with transactions)
- The
disabled
copy row is not editable. Only the pinned row can enter edit mode. - Any changes applied via the pinned row should also be reflected to its copy placeholder in the unpinned area (when edited, deleted etc.).
- Pending transaction styles are applied to both the record and its disabled copy.
- Added rows should allow pinning and should also create a copy.
- The
- Row Selection
- When the actual pinned row is selected, then the copy placeholder row is also marked as selected and vise versa.
- As row selection creates ranges with rowIds selecting a range in the pinned area between two pinned records would select the whole range in the scrollable area between these records.
- API functions that return selected records only return one instance of a selected records that is also pinned.
- Cell Selection
- Cells in the disabled copy row are selectable and can be selected via keyboard/drag select etc.
- Cells for both the pinned row and its disabled counterpart participate in the result of the
getSelectedData
method.
- Filtering
- Both pinned and unpinned rows are filtered based on the condition. The disabled copy rows are displayed in the filtering result if they match the filtering criteria.
- Search
- Search should mark results from both the pinned and unpinned area as separate results and should allow navigating between them (with findNext/findPrev API).
3.3. Globalization/Localization
Describe any special localization requirements such as the number of localizable strings, regional formats
3.4. User Interface
The UI for row pinning is exposed through the IgxActionStrip
component that allows for a contextual overlay showing actions for a row or cell. The IgxGridPinningActions
component is available for usage in the action strip and exposes the most common pinning actions as long as the action strip is initialized in a row context.
<igx-grid [data]="data" [autoGenerate]="true" #grid1>
<igx-action-strip>
<igx-grid-pinning-actions [grid]="grid1"></igx-grid-pinning-actions>
</igx-action-strip>
</igx-grid>
The pinning actions UI may be shown in a dropdown menu as well. This is done by setting the asMenuItems
property of the IgxGridPinningActions
component. More information is available in the IgxGridActionStrip
specification.
The default actions are as follows:
- For unpinned rows:
- Pin row
- For pinned rows:
- Unpin row
- Find in scrollable area
NOTE P2 Feature: the default action strip should be available with pinning actions if the user sets
rowsUI: true
in thepinning
configuration object.
3.5. Navigation
Navigation with the keyboard works similar to how navigating from and to the pinned area with column selection does, i.e. the pinned area navigation order is based on its position (top/bottom) and once the active element has to jump to the scrollable area it always jumps on an element of the first/last row of that area even if the scrollable's area scroll should change to accommodate this.
3.6. API
Name | Type | Default value | Valid values | Description |
---|---|---|---|---|
pinning | IPinningConfig | { rows: RowPinningPosition.Top } | Top / Bottom | Controls the pinning direction as a configuration object for both rows and columns |
Name | Description | Type |
---|---|---|
onRowPinning | Emitted when a column is being pinned or unpinned | IPinRowEventArgs |
Name | Parameters | Return type | Description |
---|---|---|---|
pinRow | rowID: any, index?: number | boolean | Pins the row specified by PK or ref, at the chosen index (optional) and returns if the operation succeeded |
unpinRow | rowID: any, |
boolean | Unpins the row specified by PK or ref, |
Note: unpinRow should not allow defining a custom index to unpin as we do not want to allow the user to change the original order of the data and pollute it. Unpinned row should go in its original location in the data.
ghost row
- all gridcells from theghost row
should have the state: "aria-disabled" (state)
- Excel export does not export pinned rows as Excel's frozen rows differ in purpose and behavior from igxGrid's pinned rows.
Specify all referenced external sources, incl. competitors’ links. Remove before publishing outside Infragistics