Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DataGrid] Prepare the tree structure for grouping sorting / filtering + multi field grouping #3301

Merged
merged 8 commits into from
Nov 29, 2021

Conversation

flaviendelangle
Copy link
Member

@flaviendelangle flaviendelangle commented Nov 29, 2021

Needs to be merged before next release

Extracted from #3277
Breaking compared to #2725 but not breaking compared to any released version.

  • Replace rowNode.groupingValue with rowNode.groupingKey and rowNode.groupingField. I was relying on the depth, but for the grouping columns I want to handle unbalanced groups so I need to store both the key and the field (see https://www.ag-grid.com/javascript-data-grid/grouping-unbalanced-groups/). The goal is to differentiate two grouping criteria being at the same depth but from a different field. For instance when grouping [{ director: 'A', company: 'B' }, { director: null, company: 'A' } by ['director', 'company'], both will have A as the grouping key of depth 0 but not from the same field.

  • Pass the groupingKey on the valueGetter of the grouping cell to prepare for sorting / filtering and access directly the rowNode on the component for rendering

  • Reduce the depth-margin on the grouping cell based on a feedback of @oliviertassinari (the 3 Argos diffs come from there)

@flaviendelangle flaviendelangle self-assigned this Nov 29, 2021
*/
value: PropTypes.shape({
rowNode: PropTypes.shape({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@m4theushw those transpiled files do not apply the generateProptypes config but another one stored on formattedTSDemos

I will do, a follow up PR trying to unify both 👍

@alexfauquette
Copy link
Member

There is one point I do not understand. In the code you modified, you replace path=["A", "A"] by path = [ { key: 'A', field: null }, { key: 'A', field: null }, ]. But when I look at Demo examples, they use hierarchy to define how they are grouped. Is there a link between path and hierarchy or is it two distinct things?

@flaviendelangle
Copy link
Member Author

flaviendelangle commented Nov 29, 2021

@alexfauquette buildRowTree is a method called by useGridTreeData to create the tree from the rows.
It will also be used by useGroupingColumns.

Those hooks pre-process the data to transform them into the path format buildRowTree expects.

For useGridTreeData, it is simply calling getTreeDataPath and setting the field to null
getTreeDataPath can do whatever it wants, in the example it returns the key hierarchy but I did not wanted to force a specific row format, it could return another key, concatenate two keys, etc...

      const rows = params.ids
        .map((rowId) => ({
          id: rowId,
          path: props.getTreeDataPath!(params.idRowsLookup[rowId]).map(
            (key): BuildRowTreeGroupingCriteria => ({ key, field: null }),
          ),
        }))
        .sort((a, b) => a.path.length - b.path.length);

For useGroupingColumns it is slightly more complicated because we must 1st extract the distinct values of each grouping column.

      params.ids.forEach((rowId) => {
        const row = params.idRowsLookup[rowId];

        groupingColumnsModel.forEach((groupedByField) => {
          const { key } = getCellGroupingCriteria({
            row,
            id: rowId,
            colDef: columnsLookup[groupedByField],
            field: groupedByField,
          });
          const groupingFieldsDistinctKeys = distinctValues[groupedByField];

          if (key != null && !groupingFieldsDistinctKeys.map[key.toString()]) {
            groupingFieldsDistinctKeys.map[key.toString()] = true;
            groupingFieldsDistinctKeys.list.push(key);
          }
        });
      });

      const rows = params.ids.map((rowId) => {
        const row = params.idRowsLookup[rowId];
        const parentPath = groupingColumnsModel
          .map((groupingField) =>
            getCellGroupingCriteria({
              row,
              id: rowId,
              colDef: columnsLookup[groupingField],
              field: groupingField,
            }),
          )
          .filter((cell) => cell.key != null);

        return {
          path: [...parentPath, { key: rowId.toString(), field: null }],
          id: rowId,
        };
      });

To go back to the demo example:

  • The rows have a hierarchy
  • The getTreeDataPath is called in useGridTreeData and returns this hierarchy
  • useGridTreeData processed it to add field: null and then call buildRowTree
  • buildRowTree uses this processed path to build a tree and generate the missing group nodes.

@flaviendelangle flaviendelangle merged commit 9f8bacd into mui:master Nov 29, 2021
@flaviendelangle flaviendelangle deleted the tree-multi-field branch November 29, 2021 14:23
@oliviertassinari oliviertassinari added the component: data grid This is the name of the generic UI component, not the React module! label Jan 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: data grid This is the name of the generic UI component, not the React module!
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants