ag-gridhierarchical-data

AG Grid: Can a hierarchical table with instantiated parents be flattened?


Use case

Illustrated below: A hierarchical table is two levels deep (“parents” and “children”). In some instances, our users need the hierarchy to flatten, so that the children are shown as equal to their parents. The purpose is to sort this list irrespective of the child-parent relationships. The flattening will also enable intuitive filtering of the metadata (here: Status).

enter image description here

Note:

My question: Is this flattening possible in AG Grid without creating two tables that are switched between?

“Row Grouping” or “Tree Data”?

AG Grid supports both “Row Grouping” and “Tree Data”. I am open using either one, but Tree Data seems to be necessary in order to get the desired row filter.

Fallout if creating two tables: Technical debt

We have successfully created two tables, hierarchical and flat, that can be switched between. Then, when the user wants to hide rows and store this visibility between sessions, getFilterModel() and setFilterModel() can be used to store data (in conjunction with a cookie). However, when switching between hierarchical and flat, getFilterModel's structure switches too, like so:

Flat getFilterModel:

Hierarchical getFilterModel:

This means that we must support two data structures on our backend, both for reading and writing the preferred row visibility.

First failed approach: Hide the AutoColumn

My initial approach was to hide the AutoColumn on demand. This does not seem to be working, and a comment here seems to indicate that at least five years ago, this was not possible. To demonstrate, in the code below, hiding works for parent, but not for ag-Grid-AutoColumn:

let isHierarchyVisible = gridApi.getColumn('ag-Grid-AutoColumn').isVisible();
gridApi.setColumnsVisible(['parent'], isHierarchyVisible);
gridApi.setColumnsVisible(['ag-Grid-AutoColumn'], !isHierarchyVisible);

Click Switch View (in full page view) in the snippet below to see how hiding works for parent, but not for ag-Grid-AutoColumn.

let gridApi;
const gridDiv = document.querySelector('#myGrid');
const agGridAutoColumnVisibleValue = document.querySelector('#ag-grid-auto-column-visible-value');

const columnDefs = [
  { field: 'parent', rowGroup: true, hide: true },
  { field: 'child' },
];

const rowData = [
  { parent: 'Parent A', child: 'Child A1' },
  { parent: 'Parent A', child: 'Child A2' },
  { parent: 'Parent B', child: 'A - Child B1' },
  { parent: 'Parent B', child: 'Child B2' },
];

const gridOptions = {
  columnDefs: columnDefs,
  rowData: rowData,
  //autoGroupColumnDef: { field: 'parent' },
  groupDefaultExpanded: -1,
};


function switchView() {
  let isHierarchyVisible = gridApi.getColumn('ag-Grid-AutoColumn').isVisible();
  gridApi.setColumnsVisible(['parent'], isHierarchyVisible);
  gridApi.setColumnsVisible(['ag-Grid-AutoColumn'], !isHierarchyVisible);
  agGridAutoColumnVisibleValue.textContent = gridApi.getColumn('ag-Grid-AutoColumn').isVisible();
  gridApi.refreshCells();
}

gridApi = agGrid.createGrid(gridDiv, gridOptions)
agGridAutoColumnVisibleValue.textContent = gridApi.getColumn('ag-Grid-AutoColumn').isVisible();
<script src="https://cdn.jsdelivr.net/npm/ag-grid-enterprise/dist/ag-grid-enterprise.min.js"></script>
<button onclick="switchView()">Switch View</button>
<div>ag-Grid-AutoColumn.visible value: <code id="ag-grid-auto-column-visible-value"></code></div>
<div id="myGrid" style="height: 600px;width: 600px;" class="ag-theme-alpine"></div>

Second failed approach: Use row grouping

Below is an attempt at row grouping as opposed to tree data. However, the parents' metadata does not show when collapsed, and the users objected to the way of referencing the parents using the “(self)” nomenclature and similar naming. Basically, they want the parent to occupy just one row. We tried solving this with groupHideOpenParents, but that yields issues when sorting & collapsing.

enter image description here


Solution

  • After trial & error (mostly the latter), I concluded this can't be done, and I resorted to destroying the table and recreating it from scratch when the user wants to flatten in order to sort.

    This works technically, with the usefulness & usability cost that the context is lost (navigation in the table, e.g. filtering, scrolling and collapsing of columns, is reset) or has to be reapplied at recreation (yielding additional, undesirable code/ technical debt).

    So still grateful for any non-destructive solution.