news 2026/9/14 1:39:39

NiceGUI 可编辑 AG Grid 实战:构建支持增、删、改行的数据表格

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
NiceGUI 可编辑 AG Grid 实战:构建支持增、删、改行的数据表格

NiceGUI 可编辑 AG Grid 实战:构建支持增、删、改行的数据表格

【免费下载链接】niceguiCreate web-based user interfaces with Python. The nice way.项目地址: https://gitcode.com/GitHub_Trending/ni/nicegui

导读

本指南以 NiceGUI 仓库中的 examples/editable_ag_grid 示例为核心,完整讲解如何基于ui.aggrid构建一个支持新增行、单元格内联编辑、批量删除选中行的数据表格,并深入源码剖析options数据同步、事件转发与行选择 API 的底层机制。读完本文,你将能够在自己的 NiceGUI 应用中复现一个开箱即用的可编辑表格,并掌握让服务端数据与前端网格保持一致的关键技巧。

示例总览

AG Grid 是功能强大的 JavaScript 数据网格库,NiceGUI 通过ui.aggrid元素将其封装为 Python 组件:全部网格配置以字典形式传入,Python 端通过操作options字典与浏览器端保持同步。本文对应的完整示例位于 examples/editable_ag_grid/main.py,运行方式与仓库中其他示例一致:

python main.py

启动后浏览器打开 NiceGUI 默认地址(通常为http://localhost:8080),即可看到下图所示的表格界面:

示例实现了三项核心能力:双击单元格修改数据、点击New row追加行、选中若干行后点击Delete selected批量删除,每一步操作都会通过ui.notify在页面右上角给出反馈。

一、构建可编辑网格:从一段核心配置开始

先看示例中创建网格的部分(main.py):

aggrid = ui.aggrid({ 'columnDefs': [ {'field': 'name', 'editable': True, 'sortable': True}, {'field': 'age', 'editable': True}, {'field': 'id'}, ], 'rowData': [ {'id': 0, 'name': 'Alice', 'age': 18}, {'id': 1, 'name': 'Bob', 'age': 21}, {'id': 2, 'name': 'Carol', 'age': 20}, ], 'rowSelection': {'mode': 'multiRow'}, 'stopEditingWhenCellsLoseFocus': True, }).on('cellValueChanged', handle_cell_value_change)

对配置项逐一说明:

配置键作用示例值说明
columnDefs定义列及每列的属性editable: True开启单元格编辑;sortable: True允许点击表头排序;id列不编辑、仅作行标识
rowData网格初始数据,列表中的每个字典对应一行这里初始化了三行数据
rowSelection行选择模式{'mode': 'multiRow'}表示支持多行选择(同时选中多行)
stopEditingWhenCellsLoseFocus编辑状态控制True后,单元格在失去焦点时即结束编辑并提交新值

其中stopEditingWhenCellsLoseFocus值得特别留意。从 aggrid.py 的文档注释可以看到,编辑中的单元格只有在退出编辑模式后,其数据才会被回传——而"失去焦点即退出编辑"这个行为必须显式开启。若不设置该项,用户点击网格外区域时编辑不会结束,服务端可能一直拿不到新值。

二、三种行操作:新增、编辑、删除的完整实现

2.1 新增行(add_row)

def add_row(): new_id = max((dx['id'] for dx in aggrid.options['rowData']), default=-1) + 1 aggrid.options['rowData'].append({'id': new_id, 'name': 'New name', 'age': None}) ui.notify(f'Added row with ID {new_id}')

关键点:直接修改aggrid.options['rowData']这个列表optionsAgGrid暴露的受监控字典(见源码 aggrid.py),对其中数据的修改会被 NiceGUI 检测到并自动推送到浏览器端刷新网格。新增行时用max(...) + 1生成自增id,保证新行 id 不与现有行冲突。

补充:options字典在创建时还会被自动注入theme(默认'quartz')等字段,详见 aggrid.py;auto_size_columns未显式设置时,会按"列不使用flex则自动撑满网格宽度"的规则生成autoSizeStrategy

2.2 单元格编辑与事件回传(handle_cell_value_change)

def handle_cell_value_change(e): new_row = e.args['data'] ui.notify(f'Updated row to: {e.args["data"]}') aggrid.options['rowData'][:] = [row | new_row if row['id'] == new_row['id'] else row for row in aggrid.options['rowData']]

用户编辑完成后触发cellValueChanged事件,事件对象e.args中包含 AG Grid 回传的整行数据(data字段)。回调中做两件事:

  1. ui.notify给出编辑反馈;
  2. 用编辑后的新行数据替换rowData中 id 匹配的旧行——row | new_row是 Python 3.9+ 的字典合并语法,new_row的字段会覆盖旧行同名字段。通过切片赋值rowData[:] = ...原地更新列表,确保网格能感知变更并刷新。

这一"事件驱动 + 回写 options"的模式,正是可编辑网格保持前后端数据一致性的核心套路。

2.3 删除选中行(delete_selected)

async def delete_selected(): selected_id = [row['id'] for row in await aggrid.get_selected_rows()] aggrid.options['rowData'][:] = [row for row in aggrid.options['rowData'] if row['id'] not in selected_id] ui.notify(f'Deleted row with ID {selected_id}')

删除操作分两步:

  1. await aggrid.get_selected_rows()从浏览器端取回当前所有选中行的数据;
  2. 用列表推导式过滤掉 id 在选中集合中的行,再通过切片赋值写回rowData

get_selected_rowsAgGrid提供的内置异步方法,其实现位于 aggrid.py,底层调用 AG Grid API 的getSelectedRows方法;配套的get_selected_row(aggrid.py)则在单行选择模式下返回第一行或None。官方测试 tests/test_aggrid.py 对多选与单选两种取回方式均有验证。

最后,两个按钮把三个操作串起来:

ui.button('Delete selected', on_click=delete_selected) ui.button('New row', on_click=add_row)

三、源码原理:事件如何从浏览器到达 Python

示例中.on('cellValueChanged', handle_cell_value_change)能生效,依赖 NiceGUI 为 AG Grid 建立的事件转发链路。从 aggrid.js 可以看到,网格创建后立即注册了全局监听器:

this.api = AgGrid.createGrid(this.$el, this.gridOptions); this.api.addGlobalListener(this.handle_event);

handle_event(aggrid.js)会把 AG Grid 事件参数挑选出可安全序列化的字段(如datavalueoldValuenewValuerowIndexcolId等)打包后通过$emit发送给 Python 端,Python 端即可通过.on('cellValueChanged', ...)订阅。

需要留意的是:官方文档指出,rowClicked等部分事件的参数包含循环引用,直接注册会因序列化失败而无法工作。此时可在.on()中显式限定事件参数,例如.on('rowClicked', lambda event: ui.notify(f'Row: {event.args}'), ['data']),只序列化data字段即可规避(详见 aggrid_documentation.py)。

四、进阶能力:把可编辑网格用得更好

4.1 读取客户端编辑结果:get_client_data / load_client_data

如果不想逐个监听cellValueChanged事件,可在任意时刻批量取回客户端全部(或筛选/排序后)的数据:

data = await grid.get_client_data() # 全部行(默认顺序) sorted_data = await grid.get_client_data(method='filtered_sorted') # 过滤并排序后的行 grid.load_client_data() # 直接将客户端数据回写为 options['rowData']

get_client_data支持all_unsortedfiltered_unsortedfiltered_sortedleaf四种取值方式(实现见 aggrid.py),其测试用例在 tests/test_aggrid.py 中验证了默认顺序与排序后的取回结果。同样地,它的文档注释再次强调:编辑中的单元格在退出编辑前不会更新数据,必要时请开启stopEditingWhenCellsLoseFocus

4.2 调用 AG Grid API:run_grid_method / run_row_method

run_grid_method可在 Python 端调用任意 AG Grid 网格 API(如selectAllsetColumnsVisibleapplyTransaction),run_row_method则针对指定行调用(需先用getRowId定义行 id)。二者均可await以取回返回值(aggrid.py),官方文档示例与测试均有覆盖(如 tests/test_aggrid.py 中通过run_row_method('Alice', 'setDataValue', 'age', 42)直接改写指定单元格)。

关于新增行的进阶做法:直接修改rowData会让客户端整体重建网格,正在编辑的单元格内容会丢失。若需保留未保存的编辑,可以结合grid.props.suspend_updates()与服务端applyTransaction事务 API 实现"无重建"新增,官方文档 aggrid_documentation.py 提供了完整示例。

4.3 其他实用配置

  • 列定义headerName自定义表头、hide隐藏列、filter/floatingFilter启用迷你过滤器、':getRowHeight'传 JS 函数实现动态行高(见 aggrid_documentation.py);
  • 数据源ui.aggrid.from_pandas(df)ui.aggrid.from_polars(df)可直接从 DataFrame 创建网格(aggrid.py),非 UTF-8/特殊类型列会被自动转为字符串;
  • 主题与模块:构造函数支持themequartz/balham/material/alpine,默认quartz)与modulescommunity/enterprise或自定义模块列表),当前 NiceGUI 内置的 AG Grid 版本为ui.aggrid.VERSION = '34.2.0'(aggrid.py)。

五、常见问题速查

  1. 改了rowData但界面没刷新:务必使用rowData[:] = ...原地替换或直接append,避免整体重新赋值整个options字典(后者可能触发不必要的全量重建)。
  2. 编辑后的值没被服务端感知:确认单元格已退出编辑模式,并优先开启stopEditingWhenCellsLoseFocus: True;需要批量取回时使用get_client_data
  3. rowClicked等事件不触发:事件参数含循环引用导致序列化失败,用.on(event, handler, ['data'])限定参数范围。
  4. 行 id 冲突:新增行时基于max(id) + 1生成新 id,删除时按 id 过滤,保证增删操作始终以id为唯一键对齐前后端数据。

结语

通过本文,你已掌握 NiceGUI 中可编辑 AG Grid 的完整实现路径:用columnDefs/rowData声明网格、用editable开启单元格编辑、用cellValueChanged事件 + 回写options完成数据同步,再用get_selected_rows与列表过滤实现批量删除。这套模式可直接迁移到任何需要前端表格交互的 Python 应用场景中,结合 tests/test_aggrid.py 与 aggrid_documentation.py 中的更多示例,你可以继续探索过滤、排序、复杂对象、事务更新等高级用法。

【免费下载链接】niceguiCreate web-based user interfaces with Python. The nice way.项目地址: https://gitcode.com/GitHub_Trending/ni/nicegui

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 1:39:16

SpringBoot驱动的微信小程序网络安全科普系统

简介:本资源是一套面向计算机专业本科生及毕业设计学生的全栈开发实战案例,聚焦微信小程序与SpringBoot协同架构的网络安全科普系统实现。项目覆盖前端小程序(WXML/WXSS/JS)、后端Java服务(SpringBootMyBatisSpring Se…

作者头像 李华
网站建设 2026/9/14 1:34:18

DMA与CPU缓存一致性:深入理解设备树中的dma-coherent属性

DMA 和 CPU 之间的那点“小矛盾”,我是在一次摄像头图像花屏的调试中彻底领教了。当时驱动代码里明明做了 cache 操作,但图像数据就是隔三差五出现错位和撕裂,查了一整天,最后发现问题是设备树里少了一个dma-coherent属性。从那以…

作者头像 李华
网站建设 2026/9/14 1:33:25

用ResNet18微调300张人脸图实现性别分类与检测

简介:面向深度学习算法训练的人脸性别检测与分类数据集,涵盖woman、man两类共300张真实手机采集的高质量人脸图片,均已人工分类标注,适合人脸检测、性别特征提取与分类模型的训练及评估。资源包共505个文件、约339.41MB&#xff0…

作者头像 李华
网站建设 2026/9/14 1:32:40

飞鼠格式实测:本地离线转换工具的能力边界与GPL-3.0许可证解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华