You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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),
                                                  ),
                                          ),
                                        )
                                      ],
                                    );
                                  }
                                }),
                          )),
                    ],
                  )),
            ]))));
  }
}

关键修改说明

  1. 自定义AOF数据类:用类封装每个文档的ID和名称,避免全局变量覆盖问题,每条数据都是独立对象。
  2. DropdownMenuItem存储完整对象:将下拉选项的value设置为整个AOF对象,而非仅名称,选中时可直接获取ID。
  3. 简化选择逻辑:onChanged回调直接接收AOF对象,无需通过名称反向查找ID,直接访问id和name属性即可。
  4. 清理冗余全局变量:移除原有的全局MD、idAOF2等变量,避免状态混乱。
  5. 统一Project下拉逻辑:将Project的value改为存储文档ID,通过FutureBuilder获取对应名称显示,保持逻辑一致性。

修改完成后,你可以直接通过selectedFocusCapture?.id和selectedFocusCapture?.name获取选中项的ID和名称,写入Inbox集合的文档中即可。


内容的提问来源于stack exchange,提问作者Laurent Thomas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 11:36:15