Flutter:SfDataGrid选中行跳转详情页,传递Firestore文档快照问题
解决方案
要传递Firestore文档的完整字段到详情页,核心是保留原始的Firestore文档数据在数据源中,而不是只依赖表格渲染用的DataGridRow。具体步骤如下:
1. 定义包含完整字段的数据模型
先创建一个数据模型类,比如Employee,要包含Firestore文档的所有字段(包括表格未显示的内容),同时保留文档ID方便后续操作:
class Employee { Employee({ required this.id, required this.name, required this.designation, required this.salary, this.email, this.phone, }); final String id; final String name; final String designation; final int salary; final String? email; final String? phone; // 从Firestore快照转换为模型 factory Employee.fromSnapshot(DocumentSnapshot snapshot) { final data = snapshot.data() as Map<String, dynamic>; return Employee( id: snapshot.id, name: data['name'], designation: data['designation'], salary: data['salary'], email: data['email'], phone: data['phone'], ); } }
2. 修改数据源类,存储完整模型数据
让你的EmployeeDataSource类维护一个包含完整Employee对象的列表,表格渲染只提取需要显示的列:
class EmployeeDataSource extends DataGridSource { EmployeeDataSource(this.employees) { _buildDataGridRows(); } // 保存完整的Firestore文档模型列表 final List<Employee> employees; List<DataGridRow> _dataGridRows = []; void _buildDataGridRows() { _dataGridRows = employees .map<DataGridRow>((employee) => DataGridRow(cells: [ DataGridCell<String>(columnName: 'name', value: employee.name), DataGridCell<String>(columnName: 'designation', value: employee.designation), DataGridCell<int>(columnName: 'salary', value: employee.salary), // 只渲染需要显示的列,模型保留所有字段 ])) .toList(); } @override List<DataGridRow> get rows => _dataGridRows; @override DataGridRowAdapter buildRow(DataGridRow row) { return DataGridRowAdapter( cells: row.getCells().map<Widget>((dataGridCell) { return Container( alignment: Alignment.center, padding: const EdgeInsets.all(8.0), child: Text(dataGridCell.value.toString()), ); }).toList()); } }
3. 点击行时传递完整模型到详情页
在onCellTap回调中,直接从数据源的原始模型列表中获取数据,而不是从effectiveRows取DataGridRow:
onCellTap: (DataGridCellTapDetails details) { // 减去1是因为第一行是表头 final int rowIndex = details.rowColumnIndex.rowIndex - 1; if (rowIndex >= 0 && rowIndex < employeeDataGridSource.employees.length) { // 获取包含所有字段的完整Employee对象 final Employee selectedEmployee = employeeDataGridSource.employees[rowIndex]; Navigator.of(context).push(MaterialPageRoute( builder: (context) => DataGridRowInfoPage(employee: selectedEmployee), )); } },
4. 详情页接收并展示完整数据
修改详情页,接收Employee对象并展示所有字段:
class DataGridRowInfoPage extends StatelessWidget { final Employee employee; const DataGridRowInfoPage({super.key, required this.employee}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('员工详情')), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('姓名: ${employee.name}'), Text('职位: ${employee.designation}'), Text('薪资: ${employee.salary}'), Text('邮箱: ${employee.email ?? '未填写'}'), Text('电话: ${employee.phone ?? '未填写'}'), // 可添加任意Firestore文档中的字段 ], ), ), ); } }
关键说明
DataGridRow只是表格渲染的载体,仅包含你指定要显示的列数据,因此无法从中获取完整的Firestore文档信息。- 始终在数据源中保留原始的Firestore模型数据,这样需要时能直接获取完整信息,避免数据丢失。
内容的提问来源于stack exchange,提问作者Ageu Chamene
相关产品推荐
相关产品推荐

