Skip to content

Row Pinning

Stefan Ivanov edited this page Apr 6, 2020 · 43 revisions

Row Pinning Specification

Contents

  1. Overview
  2. User Stories
  3. Functionality
  4. ARIA support
  5. Assumptions and Limitations
  6. References

Revision History

Pinned Rows are visible all the time. Horizontal scrolling is applied to the rest of the columns.

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

Objectives

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 one or more rows to the top/bottom of the grid to make them visible all the time, even when scrolling.
  • Story 2: I want to have a clear and consistent-with-pinned-columns visual indication in order to differentiate pinned from unpinned rows.
  • Story 3: I want to have a vertical scrollbar only over the scrollable portion of the grid to be able to scroll the unpinned rows up and down.
  • Story 4: I want to select several rows and pin them all at once e.g. via a grid toolbar button.

As a developer:

  • Story 1: I want to programmatically pin/unpin rows by their identifier.
  • Story 2: I want to be able to template the row to allow users to pin/unpin rows.
  • Story 3: I want to have an out of the box experience for selecting rows and pinning them as a group via a preset toolbar button.

Acceptance criteria

  1. Programmatically pin rows ...

3.1. End-User Experience

Initially, no columns or rows are pinned and the user hovers over any row, which makes an action strip show for the row and lets the user click on the pin action. A row that shows pin action in a strip upon hover

Once a row is pinned in a similar fashion it lets the user unpin rows. A pinned row that shows unpin action likewise

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.

Grid with top-pinned rows

Bottom-pinned rows should appear below the scrollable grid body (and summary rows if there are column summaries defined) and above the bottom border of the grid (or paging UI if pagination is switched on). If the page size is set to e.g. 10 records and we have 2 pinned rows, then the page should be adjusted to show 8 records, if the user pins another row, the page size is adjusted in real-time to 3.

Grid with bottom-pinned rows

Pinned records are interactive but leave a disabled copy of themselves in the main body area that receives editing updates and selection styles (when its pinned counterpart is interacted with) but is otherwise non-interactive to the end-user with the exception of being expand/collapsible in the case of a grid view supporting hierarchy (igxHierarchicalGrid, igxTreeGrid, igxGrid with Master-detail visualization). Pinned records do not display expand/collapse icons.

  • igxTreeGrid Tree Grid with Row Pinning

  • igxHierarchicalGrid Hierarchical Grid with Row Pinning

Pinned rows display contextual UI allowing end-users to find the pinned row's disabled copy in the main table body area.

TODO Add design screenshot

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.
  • Row pinning should work with Group By taking the pinned record out of its group and placing it in the pin area.
  • Grouping is not applied on the pinned records collection, however the pinned records ghost rows remain in their appropriate groups.
  • Paging includes pinned record as part of its page size and may therefore create additional pages while the end-user pins records (as the total amount of records to be displayed increases).

NOTE: Pinning records is unsuccessful if the amount of pinned records would become equal or exceed the currently set page size.

  • 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;
}

@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>();

Feature integration

Pinned rows are rendered outside of the igxForOf display container instead of using ngFor for the template structure. This requires that they are removed from the data view being passed through the pipes in certain cases and/or included in a pinned-only pipe collection. The following specifies where they are included and where they are not:

  1. gridTransaction - runs separately on both collections
  2. visibleColumns - runs on a combined collection
  3. gridFiltering - runs separately on both collections
  4. gridSort - runs separately on both collections (both pinned and unpinned columns should be sorted based on the expressions)
  5. gridGroupBy - runs only on the unpinned rows collection (pinned rows should not show group by rows)
  6. gridPaging - runs only on the unpinned collection with a modified pageSize - pageSize = pageSize - pinnedRows.length
  7. gridSummary - global summaries run on the combined collection, group by ones run only on the unpinned rows collection
  8. gridDetails - runs only on the unpinned collection. Master rows that are pinned leave ghost copies which can be expanded/collapsed.

Ghost row specific integration

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.).
    • Added rows should allow pinning and should also create a copy.
  • Row Selection
    • The pin copy is not selectable via the UI. Its checkbox is disabled.
    • When the actual pinned row is selected, then the copy placeholder row is also marked as selected.
    • When all rows are selected via the UI all rows in the pinned and unpinned area are marked as selected (including the disabled rows.)
  • Cell Selection
    • Cells in the disabled copy row are selectable and can be selected via keyboard/drag select etc.
  • 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).
  • Paging
    • As there are 2 rows associated with the same record, when a row is pinned the total items count should reflect the pinned + unpinnd rows count.

For example: If page size is 10 and 2 rows are pinned, then there should be rendered 2 pinned and 8 unpinned rows. The pager should reflect the new total items count (+ 2 due to the pinned row) and calculate the page count based on that value.

3.3. Globalization/Localization

Describe any special localization requirements such as the number of localizable strings, regional formats

3.4. User Interface

3.5. Navigation

3.6. API

Inputs

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
? UI

Outputs

Name Description Type
onRowPinning Emitted when a column is being pinned or unpinned IPinRowEventArgs

Methods

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, index?: number boolean Unpins the row specified by PK or ref, at the chosen index (optional) and returns if the operation succeeded

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.

Specify only if applicable

  • Excel does not support frozen rows at the bottom. When RowPinningPosition.Bottom is used, all pinned rows will appear as frozen at the top in Excel.

Specify all referenced external sources, incl. competitors’ links. Remove before publishing outside Infragistics

Clone this wiki locally