-
Notifications
You must be signed in to change notification settings - Fork 161
igxTreeGrid Specification
- Overview
- User Stories
- Functionality
- Test Scenarios
- Accessibility
- Assumptions and Limitations
- References
CodeX
Diyan Dimitrov
Stefan Ivanov
- Peer Developer Name | Date:
- Stefan Ivanov | Date: 18 Nov 2020
- Radoslav Mirchev | Date:
- Radoslav Karaivanov | Date:
Version | Users | Date | Notes |
---|---|---|---|
1 | Diyan Dimitrov, Stefan Ivanov | 29 Oct 2020 | Updating spec format |
The igxTreeGrid control is intended to visualize hierarchical data with consistent data schema in the tabular fashion of the igxGrid. Tree Grid's default styling follows Google's material design guidelines and is consistent with the igxGrid.
Provide Ignite UI for Angular igxTreeGrid component that supports the existing igxGrid features:
- Sorting
- Filtering
- Editing
- Paging
- Virtualization - Row and column
- Multi-column headers
- Templates
- Row, Cell and Column Selection
- Column Summaries
- Column hiding
- Column pinning
- Column moving
- Data-binding
- Export to Excel
Must-have before we can consider the feature a sprint candidate
...
Developer stories:
- Story 1: As a developer, I want to hide particular columns under certain conditions, so that I can show them again when these conditions change and it makes sense to have them visible again.
- Story 2: As a developer, I want to freeze some columns by default, so that the user is unable to move and reorder them around the grid.
- Story 3: As a developer, I want to specify if updating the content of the TreeGrid is allowed or not – is it editable or read-only.
- Story 4: As a developer, I want to show a particular node in the hierarchy upon initial rendering of the grid. I need to be able to set the number of levels which are initially expanded below the root level in order for that node’s parent to be expanded and thus the node be visible on initialization.
- Story 5: As a developer, I want to decide whether the expand state is persisted or not, so that when the grid is redrawn for any reason it either keeps this expanded state or resets it (sets it to the initial state).
- Story 6: As a developer, I want to specify which columns are allowed to be placed to the left of the grid and serve as the one to represent visually the tree hierarchy. For some columns it makes a lot of sense to do so while for others it does not make any (e.g. imagine a company organization: names, positions and departments make sense to act as tree columns while salary, starting date and type of contract do not).
- Story 7: As a developer, I want to offer aggregated information for a given level in the hierarchy of the grid. This can be achieved through a special row that can be either on top of the group of entries as a header or just below it as a footer.
- Story 8: As a developer, I want to configure whether the selection is single or multiple. By default, row selection is disabled.
- Story 9: As a developer, I want to enable a multiple selection mode in a cascading fashion. By default the multiple selection mode allows the end-user to select records one by one like in a flat grid.
- Story 10: As a developer, I want to configure whether the parents of the records matching particular filtering condition should be displayed after a filtering is applied. By default the parents are displayed in a grayed-out fashion to provide additional context.
End-user stories:
- Story 1: As an end-user, I want to have a visual indication in the form of an icon, showing that a given node (root or non-leaf) has children. The icon can be enhanced to further show the specific number of non-leaf or leaf level children that the node has.
- Story 2: As an end-user, I expect that non-leaf and leaf-level nodes are indented in a way that indicates how they relate to their parent.
- Story 3: As an end-user, I want to filter the entries for a certain column, so that only records matching the criterion that I have set are displayed and their parents in a grayed-out fashion to provide additional context. Filtering is applied to all hierarchy levels meaning that all nodes matching the criterion are shown by expanding their parents when needed.
- Story 4: As an end-user, when I am using filtering operations, I want to be able to show only the records matching particular filtering condition without any trace for their parents.
- Story 5: As an end-user, I want to sort the records in the tree grid in ascending/descending order by any column, representing the property of the entry. Sorting would work between siblings in the data hierarchy and will affect all levels and records recursively.
- Story 6: As an end-user, when I refresh the grid (or trigger another action that re-renders it) the old state of the layout (expanded/collapsed levels) should be retained and reflected after the grid is redrawn on the screen.
- Story 7: As an end-user, I want to adjust the size of the columns, so that they fit the content in a way that is suitable and useful for me.
- Story 8: As an end-user, I want to be able to pin a certain column to the left of the tree grid, and this way it will always stay visible upon horizontally scrolling the grid.
- Story 9: As an end-user, I want to hide particular columns when my current needs dictate this. Of course, later on, I need to be able to make these columns visible again.
- Story 10: As an end-user, I want to have the ability to reorder the columns in a way to help me deal with my current task without this causing any change to the hierarchy.
- Story 11: As an end-user, I expect that tree grids with a lot of records are split into pages with a certain number of items per page, and indentation is properly carried over from the current page to the next one.
- Story 12: As an end-user, I expect that records can be moved in the hierarchy, which would affect the internal structure of the data shown in the tree grid.
- Story 13: As an end-user, I want to navigate the hierarchy with the keyboard using:
- ↑ – go the row above
- ↓ – go the row below
- → – expand the node if it has children
- ← – collapse the node
- and more... TODO
- Story 14: As an end-user, I want to have a visualization of the hierarchical belonging of my currently selected item in a toolbar and be able to easily perceive how it is related to the root level of the hierarchy (e.g. an indication similar to the path to a file on the file system).
- Story 15: As an end-user, I want to have a special row that serves to aggregate information for a set of entries in the grid. This special row can be either on top of the group of entries as a header or just below it as a footer. Such header/footer is usually employed to summarize the data for a certain level of the hierarchy.
The tree grid shows hierarchical data giving context about records that have children by showing an expand indicator at the beginning of the row and indenting it according to the level it has in the hierarchy. The expand/collapse indicator also serves as a means for navigating the data.
3.1. End-User Experience
Filtering in the tree grid returns all matching records, where for records deeper in the hierarchy it also shows a trace of the direct parent hierarchy up to root level applying a grayed-out style on the parents that are not matching the filtering conditions.
In some cases, you may want the tree grid to display only the records matching particular filtering condition without any trace for their parents. This can be achieved by using the TreeGridMatchingRecordsOnlyFilteringStrategy:
Row and Cell Selection (select all included). Akin to the igx-grid, the tree grid supports none, single, and multiple as modes for row selection, but given the hierarchical nature of the data in the Tree Grid it also supports multipleCascade mode:
- none - row selection is disabled. This is the default mode.
- single - selection of only one row within the tree grid would be available.
- multiple - multiple row selection would be available by using the row selectors, with a key combination like
ctrl + click
, or by pressing thespace key
once a cell is focused. This mode allows you to select records one by one as in a flat grid (before selection on the left and after it on the right).
- multipleCascade - the selection is cascading, resulting in the selection of all children in the tree below the record that the user selects with user interaction. In this mode when a parent has some selected and some deselected children, its checkbox is in an indeterminate state. (before selection on the left and after it on the right).
If there is a filtering applied, only the filtered in child records are selected when a parent is selected. The parent checkbox state is determined only by its filtered in children. If a parent doesn't have any children after filtering and the user selects it and then the filtering is removed and the child records appear, the parent will be deselected in order to reflect the selection state of its children (which are not selected).
When selecting a range of records using the Shift
key, the selection of parent record will select all of its children even if they are not in the selected range.
Column Summaries are defined on the grid level akin to the flat grid and for any given hierarchical context or level akin to the flat grid with Group By applied.
3.2. Developer Experience
3.3. Globalization/Localization
Describe any special localization requirements such as the number of localizable strings, regional formats
3.4. Keyboard Navigation
Aside from the key combinations "inherited" from the igxGrid, the Tree Grid should also support the following keyboard interactions, accountable for the expansion and collapsing of parent records:
Keys | Description |
---|---|
Alt + → / Alt + ↓ | Expand record |
Alt + ← / Alt + ↑ | Collapse record |
→ / Tab | Move right from leftmost cell |
3.5. API
Name | Description | Type |
---|---|---|
childDataKey | Set the child data key | string |
foreignKey | Set the foreign key | string |
hasChildrenKey | Set the key indicating whether a row has children | string |
cascadeOnDelete | Indicates whether child records should be deleted when their parent gets deleted | boolean |
expansionDepth | Sets the count of levels to be expanded | number |
rowLoadingIndicatorTemplate | Provides a template for the row loading indicator when load on demand is enabled | TemplateRef |
loadChildrenOnDemand | Provides a callback for loading child rows on demand | callback |
Name | Description |
---|---|
expandAll | Expands all rows |
collapseAll | Collapses all rows |
Automation
Basic
- Scenario 1: Should have the tree-cell as a first cell on every row.
- Scenario 2: Should have a correct indentation for every record of each level.
- Scenario 3: Should expand/collapse rows through the UI by adding/removing their respective children in the grid's view underneath.
- Scenario 4: Should expand/collapse rows through the API by adding/removing their respective children in the grid's view underneath.
- Scenario 5: When expand/collapsing rows through the UI the expand/collapse indicators should change.
- Scenario 6: When expand/collapsing rows through the API the expand/collapse indicators should change.
- Scenario 7: Should be able to have a tree-column with a
number
dataType. - Scenario 8: Should be able to have a tree-column with a
string
dataType. - Scenario 9: Should be able to have a tree-column with a
date
dataType. - Scenario 10: Should be able to have a tree-column with a
boolean
dataType.
Expand/Collapse
- Scenario 1: Should update the current page when collapseAll is invoked.
- Scenario 2: Should update the current page when expandAll is invoked.
- Scenario 3: Should update the paginator when a row of any level is expanded.
- Scenario 4: Should update the paginator when a row of any level is collapsed.
- Scenario 5: Should update the paginator when navigating through pages.
Data Transformation
- Scenario 1: Should transform input data into the desired hierarchical structure given primaryKey and foreignKey are specified.
- Scenario 2: Should transform input data into the desired hierarchical structure given childDataKey is specified.
- Scenario 3: Should sort data in the desired hierarchical structure so that sorting is applied for each separate level of hierarchy.
- Scenario 4: Should correctly flatten the desired hierarchical structure with children being listed under respective parents in the correct order.
- Scenario 5: Should page the flattened data based on paging parameters.
Integration
- Scenario 1: Should persist the indentation after sorting.
- Scenario 2: Should persist the indentation after filtering.
- Scenario 3: Should persist the indentation on all pages when using paging.
- Scenario 4: Should persist the indentation after resizing the tree-column.
- Scenario 5: Should correctly render a template set through a template outlet for a column that is assigned to be the expand one.
- Scenario 6: Should transform a non-tree column into a tree column when pinning it.
- Scenario 7: Should transform a non-tree column into a tree column when hiding the original tree-column.
- Scenario 8: Should transform the first visible column into tree column when pin and hide another column before that.
- Scenario 9: Should transform a hidden column to a tree column when it becomes visible and it is the first column.
- Scenario 10: Should transform a non-tree column into a tree column when moving the original tree-column through API.
- Scenario 11: Should transform a non-tree column into a tree column when moving the original tree-column through UI.
- Scenario 12: Should be able to autosize the tree-column through API.
- Scenario 13: Should be able to autosize the tree-column through UI.
- Scenario 14: Should change cell content alignment of tree-column with number dataType when it is no longer tree-column.
- Scenario 15: Should transform a non-tree column into a tree column when hiding the original tree-column when it is part of a group.
- Scenario 16: Should transform a hidden column to a tree column when it becomes visible and it is the first column and both the original and new tree column are part of the same group.
- Scenario 17: Should transform a hidden column to a tree column when it becomes visible and it is the first column and both the original and new tree column are not part of the same group.
- Scenario 18: Should transform a non-tree column into a tree column when moving it first and both are part of the same group.
- Scenario 19: Should transform a non-tree column of a column group to a tree column when its group is moved first.
- Scenario 20: Should correctly filter a string column using the
contains
filtering conditions. - Scenario 21: Should correctly filter a string column using the
endswith
filtering conditions. - Scenario 22: Should correctly filter a number column using the
greaterThan
filtering conditions. - Scenario 23: Should correctly filter a number column using the
lessThan
filtering conditions. - Scenario 24: Should correctly filter a date column using the
before
filtering conditions. - Scenario 25: Should correctly filter a date column using the
after
filtering conditions. - Scenario 26: Should be able to search for a word in the tree column.
- Scenario 27: Should be able to search for a word in an ordinary column.
Selection
- Scenario 1: Should be able to have checkbox on each row.
- Scenario 2: Should be able to select/deselect all rows (including the rows from all child levels.
- Scenario 3: Should be able to select row of any level.
- Scenario 4: Should be able to deselect row of any level.
- Scenario 5: Should persist the selection after expand/collapse.
- Scenario 6: Should update header checkbox when reselecting all filtered-in rows.
- Scenario 7: Should return the correct type of cell when clicking on a cell.
- Scenario 8: Should return the correct type of cell when clicking on a child cell.
Cascading Selection
Basic Scenarios
- Scenario 1: Clicking on parent row`s checkbox should select the row, as well as all its leaf nodes and their leaf nodes(if any) and set their row selector checkbox state to checked. All direct and non-direct parents’ checkbox states should be set correctly as well.
- Scenario 2: Deselecting parent row should deselect all its leaf nodes and their leaf nodes(if any) and correctly set their row selector checkbox’s states. All direct and non-direct parents’ checkbox states should be set correctly as well.
- Scenario 3: Selecting all children of particular parent should select the row and set its checkbox state to selected. All direct and non-direct parents’ checkbox states should be set correctly as well.
- Scenario 4: Deselecting all children of particular parent should deselect it and set its checkbox state to deselected. All direct and non-direct parents’ checkbox states should be set correctly as well.
- Scenario 5: If all rows of particular parent are selected, deselecting one of them should deselect the parent and set its checkbox state to indeterminate. All direct and non-direct parents’ checkbox states should be set correctly as well.
- Scenario 6: If all rows of particular parent are deselected, selecting one of them should set parent’s checkbox state to indeterminate. All direct and non-direct parents’ checkbox states should be set correctly as well.
- Scenario 7: If all rows but one are deselected, deselecting this last selected row should deselect the parent row and set its checkbox state to deselected. All direct and non-direct parents’ checkbox states should be set correctly as well.
- Scenario 8: If all rows but one are selected, selecting this last non-selected row should select the parent row and set its checkbox state to selected. All direct and non-direct parents’ checkbox states should be set correctly as well.
- Scenario 9: Set nested child row, that has its own children, as initially selected and verify that both direct and indirect parent`s checkboxes are set in the correct state.
- Scenario 10: Select parent row with children not yet rendered, expand it so that all children are loaded, check whether all children checkbox states are correct - > checked.
Navigation
- Scenario 1: When selecting range of records using Shift + click key selection of parent should select all its children even if they are not in the selected range.
- Scenario 2: In case that that there are already selected rows in the grid, click on parent row that is not selected should select only the newly clicked row and its children and deselect the rest.
- Scenario 3: In case that that there are already selected rows in the grid, Ctrl + click on parent row that is not selected should add the row and its children to the selected rows collection.
Updating
Add Row
- Scenario 1: When all children of a parent are selected, respectively the parent is selected as well, and we add new row parent checkbox state -> indeterminate because newly added rows are coming as not selected.
- Scenario 2: When parent has no children and it is selected and we add child. Parent checkbox state -> not selected because newly added rows are coming as not selected.
Delete Row
- Scenario 1: When all leaf nodes are selected and we delete one of them. Parent checkbox state -> selected.
- Scenario 2: When all leaf nodes but one are selected and we delete the non-selected record. Parent checkbox state -> selected.
- Scenario 5: When we delete the only selected child of a parent row. Parent checkbox state -> not selected.
Batch Updating
- Scenario 1: When all leaf rows are selected a certain parent, we add a new leaf row and then revert transaction we should have the correct parent checkbox state -> selected.
- Scenario 2: When all rows are selected in a certain node, we add a new row and then commit transaction we should have the correct parent checkbox state -> indeterminate.
- Scenario 3: When all leaf nodes are selected and we delete one of them. Parent checkbox state -> selected.
- Scenario 4: When all leaf nodes but one are selected and we delete the non-selected record. Parent checkbox state -> selected.
- Scenario 5: When we delete the only selected child of a parent row. Parent checkbox state -> not selected.
Filtering
- Scenario 1: If there is only one selected leaf row for a particular parent and we filter it out parent`s checkbox state -> non-selected. All non-direct parents’ checkbox states should be set correctly as well.
- Scenario 2: If there is only one non-selected row for a particular parent and we filter it out parent`s checkbox state -> selected. All non-direct parents’ checkbox states should be set correctly as well.
- Scenario 3: "No rows are selected. Filter out all children for certain parent. Select this parent. It should be the only one within the selectedRows collection. Remove filtering. The selectedRows collection should be empty. All non-direct parents’ checkbox states should be set correctly as well."
- Scenario 4: Filter out all selected children for a certain parent and explicitly deselect it. Remove filtering. Parent row should be selected again. All non-direct parents’ checkbox states should be set correctly as well.
- Scenario 5: Use TreeGridMatchingRecordsOnlyFilteringStrategy and filter out a child row. The parent of the record that is matching the filtering conditions should not be displayed.
Updating + Filtering
- Scenario 1: Parent with two children, one of them selected -> indeterminate parent state. Filter out both children -> parent not selected. Select parent and add new child. Newly added child is not selected so the parent should be deselected as well. Revert filtering so that previous records are back in the view and parent should become in indeterminate state because one of it children is selected.
- Scenario 2: Parent with two selected children -> selected. Filter out one of the children and delete the other. Check parent -> not selected.
Events
- Scenario 1: selectAllRows/clearRowSelection
- Scenario 2: Cancel row selection events and check removed arguments.
- Scenario 3: Select rows using the selectRowsWithNoEvent method and check whether selection is correct. Select rows through UI and check arguments.
- Scenario 4: Change the newSelection arguments of onSelectedRowChange. The arguments SHOULD be correct.
CRUD
- Scenario 1: Should support adding root row through treeGrid API.
- Scenario 2: Should support adding child rows through treeGrid API.
- Scenario 3: Should support adding child row to
null
collection through treeGrid API. - Scenario 4: Should support adding child row to
undefined
collection through treeGrid API. - Scenario 5: Should support adding child row to
non-existing
collection through treeGrid API. - Scenario 6: Should do nothing when adding child row to a non-existing parent row (invalid parentID).
- Scenario 7: Should support updating a root row through the treeGrid API.
- Scenario 8: Should support updating a child row through the treeGrid API.
- Scenario 9: Should support updating a child row through the rowObject API.
- Scenario 10: Should support updating a child tree-cell through the treeGrid API.
- Scenario 11: Should support updating a child tree-cell through the cellObject API.
- Scenario 12: Should be able to enter edit mode of a tree-grid column on dblclick, enter and F2.
- Scenario 13: Should be able to enter edit mode of a non-tree-grid column on dblclick, enter and F2.
- Scenario 14: Should be able to edit a tree-grid cell through UI.
- Scenario 15: Should be able to edit a non-tree-grid cell through UI.
- Scenario 16: Should be able to delete a root level row by ID.
- Scenario 17: Should be able to delete a child level row by ID.
- Scenario 18: Should be able to delete a root level row through the row object.
- Scenario 19: Should be able to delete a child level row through the row object.
- Scenario 20: Should emit an event when deleting row by ID.
- Scenario 21: Should emit an event when deleting row through the row object.
Keyboard navigation
- Scenario 1:
Up Arrow Key
to navigate one cell up. Test in a child and parent rows. - Scenario 2:
Down Arrow Key
to navigate one cell down Test in a child and parent rows. - Scenario 3:
Left Arrow Key
to navigate one cell left (no wrapping between lines) on the current row only. - Scenario 4:
Right Arrow Key
to navigate one cell right on the current row only. - Scenario 5:
Page Up
scroll one page (view port) up. - Scenario 6:
Page Down
scroll one page (view port) down. - Scenario 7:
Tab
move the selection to next cell or next row if the last cell is reached. - Scenario 8:
Shift + Tab
move the selection to previous cell or previous row (last row cell) if the first cell is reached. - Scenario 9:
Tab
if a cell is opened in edit mode next cell or next row first cell (if the last cell is reached) should be opened in edit mode. If the next cell is not editable, it have to be selected. - Scenario 10:
Shift + Tab
If a cell is opened in edit mode the previous cell or previous row (last row cell) if the first cell is reached should be opened in edit mode. If the cell is not editable, it have to be selected. - Scenario 11:
Alt + Up/Left Arrow Key
the cell should stay selected and focused and if the selected cell row has children the row should be collapsed. - Scenario 12:
Alt + Down/Right Arrow Key
the cell should stay selected and focused and if the selected cell row has children the row should be expanded. - Scenario 13:
Ctrl + Up Arrow Key
move to top cell in column. - Scenario 14:
Ctrl + Down Arrow Key
move to bottom cell in column. - Scenario 15:
Ctrl + Left Arrow Key
move to leftmost cell in row. - Scenario 16:
Ctrl + Right Arrow Key
move to rightmost cell in row. - Scenario 17:
Ctrl + Home
move to top left cell in the grid. - Scenario 18:
Ctrl + End
move to bottom right cell in the grid. - Scenario 19:
Tab/Arrow keys
should navigate correctly when we have pinned columns. - Scenario 20:
Space
if Row selectors are enabled pressing space on a selected cell should select its row. - Scenario 21:
Esc
if a cell is opened in edit mode the cell edit mode should be closed and the cell should stay selected. - Scenario 22:
Enter/F2
if a cell is editable it should toggle cell edit mode.
Search
- Scenario 1: Search highlights should work for tree cells.
- Scenario 2: Search highlights should work for root and child rows.
- Scenario 3: Search highlights should work for both flat and hierarchical data.
- Scenario 4: Should navigate search highlights with collapsed rows.
- Scenario 5: Should navigate search highlights with paging.
- Scenario 6: Should navigate search highlights with paging and collapsed rows.
- Scenario 7: Search highlights should work for case sensitive and exact match searches.
- Scenario 8: Should update search highlights when filtering.
- Scenario 9: Should update search highlights when clearing filter.
- Scenario 10: Should update search highlights when sorting.
- Scenario 11: Should update search highlights after pin/unpin column.
- Scenario 12: Should update search highlights after hide/show column.
Manual Testing
- Scenario 1: igxTreeGrid is rendered correctly when initialized in igxTabs.
- Scenario 2: igxTreeGrid is rendered correctly when initialized in igxDialog.
WAI-ARIA Support In 2014 the W3C finalized their WAI-ARIA specification which defined how to design Web content and Web applications to be more accessible to users with disabilities. The TreeGrid has been designed so that it follows these guidelines.
The list below provides details about what changes have been made to the TreeGrid to support WAI-ARIA. Please note that no special settings are needed to leverage these changes, as they are all enabled by default.
RTL Support
Assumptions | Limitation Notes |
---|---|
Specify all referenced external sources