Skip to content

Hierarchical Grid Specification

Maya edited this page Apr 6, 2020 · 112 revisions

Hierarchical Grid Specification

Contents

  1. Revision History
  2. Overview
  3. User Stories
  4. Functionality
    1. End User Experience
    2. Developer Experience
    3. Globalization/Localization
    4. User Interface
    5. Navigation
    6. API
  5. ARIA support
  6. Assumptions and Limitations
  7. Test Scenarios
  8. References
Version User Date Notes
0.1 Stamen Stoychev November 11, 2018 Initial draft
0.2 Stamen Stoychev November 27, 2018 API and LoD information
0.3 Danail Marinov January 10 , 2018 End-user documentation
0.4 Martin Pavlov August 2 , 2019 Adding templates for "Collapse All" header button and "Expand/Collapse" row button
  • Stefan Ivanov | Date: 2 Aug 2019
  • Radoslav Karaivanov | Date:
  • Stamen Stoychev | Date:
  • Konstantin Dinev | Date:

Define the high-level goals

Elaborate more on the multi-facetted use cases

As a developer...

1. I should be able to apply all grid options on every grid of every level:

2. I should be able to configure grids initial expand/collapse state.

As an end user

1. I want to have option to perform Collapse all action on every row that nests another grid.

2. I want to be able to collapse all rows that belongs to a grid with one interaction (collapse all action icon in the top left corner of the header of a grid).

Details: If a grid initially has at least one row expanded, then the grid has action icon Collapse all.

Screen-Shot-2018-12-04-at-12-29-53-PM

If a grid initially has no expanded rows, then the Collapse all action icon is disabled. Note: there is no Expand all action icon by default. Expand All Action can be accomplished with custom logic.

collapse-all

Collapse all action affects only the rows belonging to the grid for which that action has been performed and does not perform collapse all for the nested grids. If a row does not include an up/down arrow in its first left cell, then it means that it does not include any nested grids. Cell selection/focusing a cell does not trigger collapse all for that row.

3. I want to be able to select and focus on a cell from a second or other level grid

2

Details: If, I, as an end user, expand at least one row that nests other grid(s) within, then "Collapse all" action icon is enabled. Then, if I select "Collapse all" action, all rows from that grid get collapsed and "Collapse all" action icon goes disabled. If, I as an end user, expand or collapse one row, it would reflect the action icon (up/down arrow) in the first left cell of the row. If, I as an end user, put focus on a cell from the top parent grid, then a 4px wide secondary color line on the left side of the row of the top parent grid appears to indicate which row nests the active cell.

4. When I select and focus a cell from a second or other level grid, I want to have visual indication which row nests the grid containing the active cell.

3 4

Details: A 4px wide secondary color line on the left side of the row of the top parent grid appears to indicate which row nests the grid containing the active cell. A 4px wide secondary color line on the left side of the whole grid that nests the active cell appears. Focusing on a cell (active cell) is what triggers the 4px wide secondary color line(s), not expanding a row within some of the grids. If I, as an end user, have no cell focused, then 4px wide secondary color line does not appear on the left. Focusing on a cell is a separate interaction and is independent from expand/collapse interaction and does not trigger expand/collapse.

4-1

5. Display density

Display density overview for compact, cozy and comfortable:

Comfortable

explanation-comfortable

Cozy

explanation-cozy

Compact

explanation-compact

6. Loader

Loading indicator (indeterminate circular or linear progress bar) appears when a child grid(s) requires to display ongoing process of initial loading. The loader appears within the child grid/grids that is loading, e.g. if in the visible area a user can see 3 grids that require loading, then each of them will display progress indicator. If a row nests a grid/grids which require loading, then the loading progress will be triggered by expanding the row. Grid(s) start loading only if needed, after expanding the row that nests these grid(s) or when a user reach them after scrolling down. A grid that needs to load before displaying records, has a fixed height of 100px (based on the height of two rows on comfortable display density).

Circular-progress

Linear-progress

7. Scroll behavior

The scroll behavior concerns the cases when the user has two or more nested grids. Then, each of the grids has its own scroll if needed depending on its height, number of rows, which of the rows are expanded etc. Naturally, the position of the mouse pointer defines which grid is being scrolled - for example if the mouse pointer is above the second level grid from 4 grids totally, the second level grid would be scrolled. It the user scrolls down/up to the end/beginning of a grid, then its first parent grid starts scrolling down/up. The default preloader is indeterminate circular loader.

8. Nothing to display

If a row does not consist any records, then empty grid template is being displayed.

Acceptance criteria

Must-have before we can consider the feature a sprint candidate

  1. IgxHierarchicalGrid should be able to bind to and display hierarchical data in a "grid of grids"-style view
  2. Each row island should expose the same configuration options as a stand-alone IgxGrid
  3. Multiple row islands per parent can be defined for separate child properties for that record
  4. Row islands are displayed after their parent row is "expanded"
  5. Child grid states are preserved during scrolling
  6. Users may enable features for each row island separately and all features for igxGrid are available for child row islands ...

Describe behavior, design, look and feel of the implemented feature. Always include visual mock-up

IgxHierarchicalGrid follows the design guidelines of IgxGrid and has similar API and UI.

Initialization

Initializing an IgxHierarchicalGrid is done through a tag of its own.

<igx-hierarchical-grid #grid1 [data]="localData" [autoGenerate]="true">
</igx-hierarchical-grid>

Hierarchical row islands are initialized through a component without a template, so that Angular's rendering pipe does not try to create child grids before they are expanded.

<igx-row-island [key]="'childData'" [autoGenerate]="true" [rowSelectable]='true'>
</igx-row-island>

Both IgxHierarchicalGridComponent and IgxRowIslandComponent expand from a single abstract class IgxHierarchicalGridBaseDirective that exposes the common API. The difference between the two is that while the IgxHierarchicalGrid is bindable and therefore has a data property, IgxRowIsland does not. Instead it has a key property determining the parent property holding the data.

Multiple islands per row are supported and are displayed in the order they are specified. Each island should have an unique key. The last island from those using duplicate keys is initialized while the rest are ignored.

A simplified diagram of the classes used to create a hierarchical grid follows:

Hierarchical Grid Diagram

Row Islands Auto Generation

Row islands may not be auto-generated. Each one should be described in the hierarchical grid template.

Using IgxRowIsland and IgxHierarchicalGrid Instances

The top-most instance is of type IgxHierarchicalGridComponent. It spawns a number of instances of type IgxRowIslandComponent equal to those defined. To access a specific row island users should reference their instance inside the template.

    <igx-hierarchical-grid [data]="localData" [autoGenerate]="true">
        <igx-row-island [key]="'childData1'" [autoGenerate]="true" #child1>
        </igx-row-island>
        <igx-row-island [key]="'childData2'" [autoGenerate]="true" #child2>
        </igx-row-island>
    </igx-hierarchical-grid>

IgxRowIslandComponent initializes IgxHierarchicalGridComponent instances upon row expansion. Option changes on a row island propagate down to its child hierarchical grid instances.

The hierarchical grid instances are uniquely identified by a complex key that is the chain of row island keys and row identifiers that are its parents. If there is no primary key for rows, rowID would return row instance. The structure is represented by the following.

    export interface IPathSegment {
        rowID: any,
        rowIslandKey: string
    }

    export class IgxHierarchicalGridComponent extends IgxHierarchicalGridBaseDirective {
        public id: Array<IPathSegment>;
    }

The hierarchical grid exposes methods that allow to obtain children through such path ids. Partial paths are accepted when the methods are called for child instances and work relatively to the position in the hierarchy the method is called for.

Hierarchical Grid Pipes

There is one specific pipe for hierarchical grids that is responsible for adding elements to initialize row islands in when the row is expanded. The expansion state is read from and applied from the following property of each hierarchical grid.

    @Input()
    public expansionStates = new Map<any, boolean>();

States are stored per row identifier and represent a state the is opposite to the default one determined by the childrenExpanded input.

Load on Demand

Loading on demand is done on application level when the key for a row island does not represent a property in the parent data source (data is only available for each island when requested). Users can subscribe to the onGridCreated output to bind newly created grids for certain island based on client-server communication implementation of their own.

    export interface IGridCreatedEventArgs {
        parentId: any;
        owner: IgxRowIslandComponent;
        grid: IgxHierarchicalGridComponent;
    }
    
    @Output()
    public onGridCreated = new EventEmitter<IGridCreatedEventArgs>();

Using the information from the parent record identifier (PK or object reference) and the row island instance users are able to obtain the context of the created grid.

Expand Row Indicator

By default the expand indicator is always visible no matter whether children grids have data or not. This is because in Load on Demand scenario there will be no data in the child grids, but still the end-user should be able to expand the row. Expand/collapse indicator visibility can be customized with hasChildrenKey input, which holds the property/field in the data source indicating if there are children. The indicator can also be customized with template. This is done via rowExpandedIndicatorTemplate property. The default template property is defaultExpandedTemplate and has the following template:

<ng-template #defaultExpandedTemplate>
    <igx-icon fontSet="material">expand_more</igx-icon>
</ng-template>

Collapse Row Indicator

By default the collapse indicator is always visible no matter whether children grids have data or not. This is because in Load on Demand scenario there will be no data in the child grids, but still the end-user should be able to expand the row. Expand/collapse indicator visibility can be customized with hasChildrenKey input, which holds the property/field in the data source indicating if there are children. The indicator can also be customized with template. This is done via rowCollapsedIndicatorTemplate property. The default template property is defaultCollapsedTemplate and has the following template:

<ng-template #defaultCollapsedTemplate>
        <igx-icon fontSet="material">chevron_right</igx-icon>
</ng-template>

Collapse All Header Indicator

By default igxHierarchicalGrid provides an UI for the end users to collapse all rows. Other scenarios can be achieved by customizing the template of the "Collapse All" Indicator. This is done via igxHeaderExpandedIndicator property. The default template property is defaultExpandedTemplate and has the following template:

<ng-template #defaultExpandedTemplate>
    <igx-icon role="button" [isActive]='true' fontSet="material">unfold_less</igx-icon>
</ng-template>

Expand All Header Indicator

By default igxHierarchicalGrid doesn't provide an UI for the end users to expand all rows. As expanding all rows might lead to performance degradation the indicator is disabled by default. In order to show the expand all icon, the showExpandAll option should be set to true for the related hierarchical grid or row island.

Example - enabling expand all header icon

 <igx-hierarchical-grid [data]="localData" [showExpandAll]="true">
 </igx-hierarchical-grid>

Other scenarios can be achieved by customizing the template of the "Expand All" Indicator. This is done via igxHeaderCollapsedIndicator property. The default template property is defaultCollapsedTemplate and has the following template:

<ng-template igxHeaderCollapsedIndicator let-hgrid>
	<igx-icon role="button" fontSet="material" >add</igx-icon>
</ng-template>

Feature Integration

The following grid features work on a per grid level, which means that each grid instance manages these features independently from the rest of the grids.

  • Sorting
  • Filtering
  • Paging
  • Multi-column headers
  • Hiding
  • Pinning
  • Moving
  • Summaries

The following features work on the whole hierarchical grid as follows:

  • Updating

    Updating requires a special service to function correctly with IgxHierarchicalGrid as each grid inside is a separate component and comes with a separate transaction log. In order to achieve that a service factory should be provided that creates new service instances for each component. A provider that can be imported in user applications is exposed as:

        export const IgxHierarchicalTransactionServiceFactory = {
        provide: IgxGridTransaction,
        useFactory: () => {
               return () => new IgxHierarchicalTransactionService()
            }
        }

    As the grid components of a single row island all show entities of the same type and are likely bound to the same remote end-point, child IgxHierarchicalGridComponent-s use the same service instance defined for their parent IgxRowIslandComponent. This means that users can obtain and operate with the transactions for every child grid of a given row island with the transactions property of the row island itself. Adding and deleting rows should still be done through the API of the separate IgxHierarchicalGridComponents.

  • Selection

    Only one cell can be selected for the whole hierarchical grid instance.

  • Navigation

    When navigating up/down if next/prev element is child grid navigation will continue in the related child grid, marking the related cell as selected and focused. In case child cell is outside the current visible view port it should be scrolled into view so that selected cell is always visible.

  • Search

    Search (findNext/findPrev API) highlights all occurrences of the searched string in parent and existing child grids. When active highlight changes the grid scroll so that the cell holding the active highlight is in view. In case the active highlight is inside a child grid, whose parent row is collapsed, the related row will be expanded.

The following features are no supported and not exposed in the API of the Hierarchical Grid.

  • Group By

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

Include a diagram linking the elements with the visual representation of the feature

Each grid in the hierarchy (parents and children) contain the same tab stops as the base igxGrid - root element, header, body and footer. As such when navigating with TAB/SHIFT+TAB those elements will be traversed as is their order in the visible DOM.

Each row island participates in the same navigation sequence for navigating up/down via the arrow keys. Navigation continues inside the deeper levels in the hierarchy. When navigation enters a child grid focus will move to the tbody of the related child grid.

Apart from key combinations "inherited" from the IgxGrid, IgxHierarchicalGrid also supports the following keyboard interactions for expanding and collapsing records.

Feature Key combination
Expand row (cell) ALT + RIGHT / DOWN
Collapse row (cell) ALT + LEFT / UP

Inputs

  • IgxHierarchicalGridBaseDirective

    Name Description Type Default value Valid values
    hierarchicalState An array of record identifiers with expand state that differs from the default. Array<any> []
    expansionStates Gets/Sets the current expansion state of the records. Contains key-value pairs [row ID, expansion state, which is true if expanded, false if collapsed] that define the expanded state of the data rows. Map<any, boolean> new Map<any, boolean>()
  • IgxHierarchicalGrid extends IgxHierarchicalGridBaseDirective

    Name Description Type Default value Valid values
    data The hierarchical grid data source Array<any> null
  • IgxRowIslandComponent extends IgxHierarchicalGridBaseDirective

    Name Description Type Default value Valid values
    key Unique identifier for the row island and the property to read for the array to bind to from a parent row string null
    expandChildren Should child island be expanded. Setting it during runtime will expand or collapse all rows boolean false true
    hasChildrenKey Contains the property(boolean) in the data source, if any, that indicates whether there are children. When not set inherits the setting from IgxHierarchicalGrid string
    showExpandAll Determined whether the hierarchical grids for this row island should show an expand all icon. When not set inherits the setting from IgxHierarchicalGrid boolean false true

Methods

  • IgxHierarchicalGridBaseDirective

    Name Description Return type Parameters
  • IgxHierarchicalGrid

    Name Description Return type Parameters
    expandAll Expands all rows of the current hierarchical grid
    collapseAll Collapses all rows of the current hierarchical grid
    expandRow(rowID) Expands the row by its id. ID is either the primaryKey value or the data record instance. rowID: any
    collapseRow(rowID) Collapses the row by its id. ID is either the primaryKey value or the data record instance. rowID: any
    toggleRow(rowID) Toggles the row by its id. ID is either the primaryKey value or the data record instance. rowID: any
  • IgxRowIsland

    Name Description Return type Parameters

Outputs

  • IgxHierarchicalGrid

    Name Description Cancelable Parameters
    onRowToggle Emitted when the expanded state of a row gets changed. true rowID: any, expanded: boolean, event?: Event, cancel: boolean
  • IgxRowIsland

    Name Description Cancelable Parameters
    onGridCreated Emitted when a grid is being created for this row island false parentRecord: any, owner: IgxRowIslandComponent, grid: IgxHierarchicalGridComponent

Properties

  • IgxHierarchicalGridBaseDirective

    Name Description Type Default value Valid values
    rowExpandedIndicatorTemplate The custom template, if any, that should be used when rendering the expanded button TemplateRef<any>
    rowCollapsedIndicatorTemplate The custom template, if any, that should be used when rendering the collapsed button TemplateRef<any>
    hasChildrenKey Contains the property(boolean) in the data source, if any, that indicates whether there are children. If set and there are no children the expandAll/collapseAll APIs won't have effect on those rows. string
    showExpandAll Determined whether the hierarchical grid should show an expand all icon. boolean false true
  • IgxHierarchicalGrid

    Name Type Getter Setter Description
    foreignKey any true false The unique identifier of the parent row

Specify only if applicable

Assumptions Limitation Notes

Basic:

  • Should render expansion indicator as the first element of each expandable row
  • Should allow expand/collapse rows through the UI
  • Should change expand/collapse indicators when state of the row changes
  • Should expand/collapse all rows that belongs to a grid with one interaction
  • Should allow applying initial expansions state for certain rows through expansionStates option
  • Should have appropriate indentation the expanded row islands
  • Should change all elements related to hierarchical grid(expansion indicators, expand all/collapse all button, "no data to display" text, etc.) when changing display density
  • Should be able to define more than one nested row island
  • Should not show header expand/collapse button if grid has no expandable rows.
  • Should render last cell of rows fully visible when columns do not have width specified and without scrollbar.

Virtualization:

  • Should retain expansion state when scrolling.
  • Should retain child scroll position when expanding and collapsing through rows.
  • Should retain child grid states (scroll position, selection, filtering, paging etc.) when scrolling.
  • Should render correct data for child grid after scrolling and start index changes.
  • Should not lose scroll position after expanding/collapsing a row.
  • Should reset scroll position after expanding/collapsing all rows.
  • Should update scroll height after expanding/collapsing rows.
  • Should be able to scroll last row in view after all rows get expanded.
  • Should render correct data for child grids when all rows get expanded.

Row Island:

  • Should allow initializing multiple child grids.
  • Should apply the set options on the row island to all of its related child grids.
  • Should apply runtime option changes to all related child grids (both existing and not yet initialized).
  • Should apply column settings applied to the row island to all related child grids.
  • Should allow setting different height/width in px/percent for child grids and grids should be rendered correctly.

Keyboard navigation:

Automation:

  • Should expand/collapse records using keyboard using key combination alt + right/down and alt + left/up
  • Should move the focus inside its first child grid when pressing Arrow Down while the focus is on the parent cell of an expanded row.
  • Should move the focus inside its last child grid when pressing Arrow Up while the focus is on a cell from the next parent row.
  • When navigating inside child grid should keep the focused/selected cell in view.
  • Should allow navigation between sibling child grids (when having multiple sibling row islands).
  • Should scroll child grid to top/bottom when navigating down/up from a parent row so that navigation starts from the first/last cell.
  • Should scroll to first/last data row when using CTRL + HOME/ CTRL + END and CTRL + Arrow Down/ CTRL + Arrow Up.

Manual:

  • Test if you can navigate using Up/Down arrow keys without losing focus from start to end in a grid with expanded nested children and multiple sibling row islands.
  • Test if navigation up/down works as expected when children have large summary rows.

Feature Integration

MCH:

  • Should allow initializing hierarchical grid with multi - column headers

Updating:

  • Should have separate instances of updating service for parent and children and the same for children of the same island

Selection:

  • Should allow only one cell to be selected in the whole hierarchical grid.
  • Should apply indication to the current and parent grids when a cell from a grid in it is selected

Load On Demand:

Automation:

  • Should show loading indicator while fetching data for expanded row islands
  • Should show "Nothing to display" when there is no data for the expanded row island
  • Should emit the onGridCreated event with the correct event args when a row is expanded and a new child grid is created.

Manual:

  • Should not render scrollbar for child grid when it doesn't have widths defined for the columns and there are more levels further down.

Pinning:

  • Pinning area separator shouldn't overlap row islands when rows are expanded

Sorting

  • Child grids data should be correct after sorting parent grid.

Moving

  • Should not be possible to drag move a column from another grid.

Summaries

  • Should render expansion cell so they don't appear misaligned.
  • Should allow defining summaries for child grid and child grid should be sized correctly.

Paging

  • Paging should work on data records only. Should not be affected by child grid rows.
  • Expansion states should not be lost after changing pages.

Filtering

  • Should allow filtering in hierarchical grid.
  • Should not lose expansion states after filtering in parent grid.

Search

  • Should highlight all cells in parent and in existing children.
  • Should highlight all cells in parent and in children when they get created.
  • Should honor the visible rows order when moving active highlight.
  • clearSearch should remove higlights from parent and child grids.
  • Should scroll to cell with active highlight in child grid, if child is not in view.
  • Should expand parent row and scroll child in view when active highligh moves to child grid in collapsed row.
  • Should change page and scoll to the cell with active highlight when there are expanded records.

Toolbar

  • Should display and apply changed for columns for current grid.

igxTabs

  • Should render correctly when initialized in non active tab
  • Should render correctly when initialized in active tab

igxDialog

  • Should render correctly when initialized in non visible dialog
  • Should render correctly when initialized in visible dialog

Specify all referenced external sources

Clone this wiki locally