Firebase Firestore无法获取对应记录ID,仅返回最后一条文档ID求助
解决Firestore下拉菜单无法获取对应文档ID的问题
你当前的问题出在两个关键点:
- 全局变量
MD在循环遍历AOF文档时,每次都会被新的文档数据覆盖,最终只保留最后一条记录的信息 - DropdownMenuItem的
value仅存储了AOF名称,无法通过名称关联到对应的文档ID,自然拿不到选中项的正确ID
修改后的完整代码
import 'package:flutter/material.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; // 自定义AOF数据类,封装文档ID和名称 class AOF { final String id; final String name; AOF({required this.id, required this.name}); } class CaptureV2 extends StatefulWidget { const CaptureV2({Key? key}) : super(key: key); @override _CaptureV2State createState() => _CaptureV2State(); } class _CaptureV2State extends State<CaptureV2> { final GlobalKey<FormState> _captureFormKey = GlobalKey<FormState>(); String? selectedProjectCapture; // 改为存储AOF对象,而非单纯字符串 AOF? selectedFocusCapture; String? _valueTaskNameChanged = ''; String? _valueTaskNameSaved = ''; @override void initState() { super.initState(); } @override Widget build(BuildContext context) { double height = MediaQuery.of(context).size.height; return Material( child: Scaffold( appBar: AppBar( centerTitle: true, title: const Text('TEMP'), actions: const <Widget>[ Padding( padding: EdgeInsets.fromLTRB(0, 22, 0, 0), child: Text("TEST"), ), ], ), body: SingleChildScrollView( child: Column(children: [ Form( key: _captureFormKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ Container( decoration: const BoxDecoration( border: Border( top: BorderSide(width: 1.0, color: Colors.grey), ), ), ), // Task Name输入框 Theme( data: ThemeData( inputDecorationTheme: const InputDecorationTheme( border: InputBorder.none, )), child: Card( child: Padding( padding: const EdgeInsets.fromLTRB( 8.0, 0.0, 15.0, 1.0), child: TextFormField( decoration: const InputDecoration( hintText: "Task Name", hintStyle: TextStyle(color: Color(0xff29B6F6)), ), keyboardType: TextInputType.text, maxLength: 100, maxLines: 3, onChanged: (valTaskName) => setState( () => _valueTaskNameChanged = valTaskName), validator: (valTaskName) { return valTaskName!.isEmpty ? "Task name cannot be empty" : null; }, onSaved: (valTaskName) => setState( () => _valueTaskNameSaved = valTaskName), ), ), )), // Project下拉菜单 Theme( data: ThemeData( inputDecorationTheme: const InputDecorationTheme( border: InputBorder.none, )), child: Padding( padding: const EdgeInsets.fromLTRB(8.0, 3.0, 0.0, 0.0), child: StreamBuilder<QuerySnapshot>( stream: FirebaseFirestore.instance .collection('Users') .doc(FirebaseAuth.instance.currentUser!.uid) .collection('projects') .snapshots(), builder: (context, snapshot) { if (!snapshot.hasData) { return const Text("Loading....."); } else { List<DropdownMenuItem<String>> projectItems = []; for (int i = 0; i < snapshot.data!.docs.length; i++) { DocumentSnapshot snap = snapshot.data!.docs[i]; projectItems.add( DropdownMenuItem( value: snap.id, child: SizedBox( width: MediaQuery.of(context) .size .width * 0.89, child: Text( "${snap['project_Name']}---${snap.id}", style: const TextStyle( color: Colors.black, fontSize: 16), ), ), ), ); } return Row(children: <Widget>[ DropdownButton<String>( items: projectItems, onChanged: (String? myProjectId) { setState(() { selectedProjectCapture = myProjectId; }); }, value: selectedProjectCapture, isExpanded: false, hint: SizedBox( width: MediaQuery.of(context).size.width * 0.89, height: 40.0, child: selectedProjectCapture == null ? const Text( 'Project ?', style: TextStyle( color: Color(0xff29B6F6), fontSize: 16), ) : FutureBuilder<DocumentSnapshot>( future: FirebaseFirestore.instance .collection('Users') .doc(FirebaseAuth.instance.currentUser!.uid) .collection('projects') .doc(selectedProjectCapture) .get(), builder: (context, projectSnap) { if (!projectSnap.hasData) { return const Text("Loading..."); } return Text( "${projectSnap.data!['project_Name']}---${selectedProjectCapture}", style: const TextStyle( color: Colors.black, fontSize: 16), ); }, ) ), ) ]); } }), ), ), // AOF下拉菜单(核心修改部分) Theme( data: ThemeData( inputDecorationTheme: const InputDecorationTheme( border: InputBorder.none, )), child: Padding( padding: const EdgeInsets.fromLTRB(8.0, 3.0, 0.0, 0.0), child: StreamBuilder<QuerySnapshot>( stream: FirebaseFirestore.instance .collection('Users') .doc(FirebaseAuth.instance.currentUser!.uid) .collection('area_of_Focus') .snapshots(), builder: (context, snapshot) { if (!snapshot.hasData) { return const Text("Loading....."); } else { List<DropdownMenuItem<AOF>> aofItems = []; // 将每个Firestore文档转换为AOF对象 final aofList = snapshot.data!.docs.map((doc) => AOF( id: doc.id, name: doc['name'] as String, )).toList(); for (var aof in aofList) { aofItems.add( DropdownMenuItem<AOF>( value: aof, // 存储完整AOF对象 child: Text( aof.name, style: const TextStyle(color: Colors.black), ), ), ); } return Row( mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[ DropdownButton<AOF>( icon: const Icon( Icons.arrow_downward_outlined), items: aofItems, onChanged: (AOF? selectedAof) { setState(() { selectedFocusCapture = selectedAof; // 直接获取选中项的ID和名称 if (selectedAof != null) { print("选中的AOF名称: ${selectedAof.name}"); print("选中的AOF ID: ${selectedAof.id}"); } }); }, isExpanded: false, value: selectedFocusCapture, hint: SizedBox( width: MediaQuery.of(context).size.width * 0.89, height: 40.0, child: selectedFocusCapture == null ? const Text( 'Area of focus ?', style: TextStyle( color: Color(0xff29B6F6)), ) : Text( selectedFocusCapture!.name, style: const TextStyle( color: Colors .black), ), ), ) ], ); } }), )), ], )), ])))); } }
关键修改说明
- 自定义AOF数据类:用类封装每个文档的ID和名称,避免全局变量覆盖问题,每条数据都是独立对象。
- DropdownMenuItem存储完整对象:将下拉选项的
value设置为整个AOF对象,而非仅名称,选中时可直接获取ID。 - 简化选择逻辑:
onChanged回调直接接收AOF对象,无需通过名称反向查找ID,直接访问id和name属性即可。 - 清理冗余全局变量:移除原有的全局
MD、idAOF2等变量,避免状态混乱。 - 统一Project下拉逻辑:将Project的
value改为存储文档ID,通过FutureBuilder获取对应名称显示,保持逻辑一致性。
修改完成后,你可以直接通过selectedFocusCapture?.id和selectedFocusCapture?.name获取选中项的ID和名称,写入Inbox集合的文档中即可。
内容的提问来源于stack exchange,提问作者Laurent Thomas
相关产品推荐
相关产品推荐

