ag-grid之分组(Grouping)还是树形数据(Tree Data):我要树形数据(Tree Data)

1,048 阅读5分钟

引言

当我们提到树结构时,其实是指表格数据中存在某种层级关系,这种关系可以通过不同的方式表示:

  1. 扁平数组格式:数据按行存储,每行数据之间通过parentIdid等字段建立关联,或者通过path字段指定层级关系。
  2. 树结构数组格式:数据本身就是树形结构,每个节点包含一个children字段,表示当前节点的子节点。

在ag-grid中,这两种方式都可以用来展示树形数据。根据不同的数据结构,ag-grid会提供不同的配置方式。

提示:本文使用的ag-grid版本是v33,请确保在相应版本下应用代码示例。此外,尽管在官网文档中没有找到treeDataChildrenField属性,并且AgGridReact没有这个属性的TS声明,但我们依然可以使用。

一、提供树形数据的模型 TreeDataModule

import { TreeDataModule } from 'ag-grid-enterprise';
ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  TreeDataModule,
  ValidationModule /* Development Only */,
]);

二、两种数据格式的配置

1. 树形结构数组格式

在这种格式中,数据本身就是树形结构,每个节点包含一个children字段,表示当前节点的子节点。

示例代码:

const gridOptions = {
    treeData: true,                     // 启用树形数据
    treeDataChildrenField: 'children',  // 指定树结构的子节点字段
    columnDefs: [{ field: 'jobTitle' }],// 定义列
    rowData: [
        {
            id: 1,
            name: 'Erica',
            jobTitle: 'CEO',
            children: [
                {
                    id: 2,
                    name: 'Malcolm',
                    jobTitle: 'VP',
                    children: [
                        {
                            id: 3,
                            name: 'Lisa',
                            jobTitle: 'Manager',
                        },
                        {
                            id: 4,
                            name: 'Robert',
                            jobTitle: 'Manager',
                        },
                    ],
                },
            ],
        },
    ],
};

在这个示例中,数据通过children字段定义了父子节点关系。treeDataChildrenField: 'children'指示ag-grid使用children字段作为子节点字段。

treeDataChildrenField的优先级比getDataPath高。

注意:如果你使用的是ag-grid v33版本,treeDataChildrenField不是标准文档中的官方属性,但依然可以在v33中正常工作。在v32之前treeDataChildrenField好像不是必须的。


2. 扁平数组格式

在这种格式中,数据是一个平面数组,每个节点通过path字段或parentId与其他节点建立关联。为了让ag-grid正确渲染这些关联数据,我们需要用getDataPath方法来指定每个节点的层级路径。

示例代码:

const rowData = [
    { id: 1, name: 'Erica', jobTitle: 'CEO', path: ['Erica'] },
    { id: 2, name: 'Malcolm', jobTitle: 'VP', path: ['Erica', 'Malcolm'] },
    { id: 3, name: 'Lisa', jobTitle: 'Manager', path: ['Erica', 'Malcolm', 'Lisa'] },
    { id: 4, name: 'Robert', jobTitle: 'Manager', path: ['Erica', 'Malcolm', 'Robert'] },
];

const gridOptions = {
    treeData: true,
    getDataPath: (data) => data.path,  // 根据path字段获取层级关系
    columnDefs: [{ field: 'jobTitle' }],
    rowData,
};

3. getDataPath的作用

getDataPath是一个回调函数,用来告诉ag-grid如何根据path字段构建树形结构。path表示从根节点到当前节点的完整路径,确保ag-grid能够正确显示层级。

1. path表示什么?

path是一个数组,表示节点的层级路径。路径从根节点开始,直到当前节点。例如,path: ['Erica', 'Malcolm', 'Lisa']表示LisaMalcolm的子节点,MalcolmErica的子节点。

2. 使用parentIdid格式时如何配置getDataPath

如果数据使用parentIdid格式来表示层级关系,getDataPath需要根据这些字段动态构建路径。我们可以使用递归查找或其他方式来生成每个节点的path

示例代码:

typescript
复制编辑
const rowData = [
    { id: 1, name: 'Erica', jobTitle: 'CEO', parentId: null },
    { id: 2, name: 'Malcolm', jobTitle: 'VP', parentId: 1 },
    { id: 3, name: 'Lisa', jobTitle: 'Manager', parentId: 2 },
    { id: 4, name: 'Robert', jobTitle: 'Manager', parentId: 2 },
];

const gridOptions = {
    treeData: true,
    getDataPath: (params) => {
        const path = [];
        let current = params.data;
        while (current) {
            path.unshift(current.name);  // 通过节点名称构建路径
            current = rowData.find(item => item.id === current.parentId);  // 查找父节点
        }
        return path;
    },
    columnDefs: [{ field: 'jobTitle' }],
    rowData,
};

在这个示例中,getDataPath使用递归查找parentId来构建path,最终生成树形结构。可以看出是比较复杂的,因为ag-grid要求的path是一个从根节点开始,直到当前节点的完整层级数组,但是parentId只能找到父级节点,所以一般情况下,如果后端返回的数据是这样的,我们会先统一处理一下,获取到path。


四、常用属性

1. autoGroupColumnDef

autoGroupColumnDef用来自定义树形数据中自动生成的分组列。默认情况下,ag-grid会生成一个“Group”列,但你可以通过autoGroupColumnDef来自定义该列的标题、显示字段等。

示例代码:

typescript
复制编辑
const gridOptions = {
    treeData: true,
    autoGroupColumnDef: {
        headerName: 'Job Title',  // 自定义分组列的标题
        field: 'jobTitle',        // 使用jobTitle字段展示这一列的数据
        cellRendererParams: {
            suppressCount: true,  // 不显示节点数量
        },
    },
    columnDefs: [{ field: 'jobTitle' }],
    rowData,
};

2. groupDefaultExpanded & isGroupOpenDefault

这两个属性控制树形数据的初始展开状态:

  • groupDefaultExpanded:指定树形数据在加载时,默认展开的层级。
  • isGroupOpenDefault:控制每个节点是否默认展开,允许为不同节点设置不同的展开状态。

示例代码:

typescript
复制编辑
const gridOptions = {
    treeData: true,
    groupDefaultExpanded: 1,  // 默认展开第一层节点
    isGroupOpenDefault: (node) => node.data.jobTitle === 'VP',  // 只有职位为'VP'的节点才会展开
    columnDefs: [{ field: 'jobTitle' }],
    rowData,
};

五、总结与实际应用

ag-grid的树形数据功能为我们提供了强大的工具来展示和处理层级结构的数据。无论是使用扁平数组格式还是树形结构格式,ag-grid都能够高效地渲染和展示层级关系。

  • 通过灵活配置getDataPathautoGroupColumnDef等属性,我们能够根据不同的需求定制树形数据的展示效果。
  • 本文提供了关于treeDatagetDataPath的基础知识,希望能够帮助你更好地理解如何在实际项目中应用这些功能。