如何将 Firestore 文档列表绑定到 Flutter 中的下拉菜单?

Posted

技术标签:

【中文标题】如何将 Firestore 文档列表绑定到 Flutter 中的下拉菜单?【英文标题】:How to bind a Firestore documents list to a Dropdown menu in Flutter? 【发布时间】:2019-03-20 06:47:52 【问题描述】:

我在下拉菜单和 Firestore 方面遇到问题,如何将从 firestore 检索到的文档列表绑定到 DropdownButton?目前我遇到了这个错误:

The argument type '(Map<dynamic, dynamic>) → DropdownMenuItem<String>' can't be assigned to the parameter type '(DocumentSnapshot) → dynamic'.

我的小部件 .dart 中的代码:

import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

class MessageList extends StatelessWidget 
  MessageList(this.firestore);

  final Firestore firestore;
  var _mySelection;

  @override
  Widget build(BuildContext context) 
    return StreamBuilder<QuerySnapshot>(
      stream: firestore.collection('preciso-modelos').snapshots(),
      builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) 
        if (!snapshot.hasData) return const Text('Loading...');
        return new DropdownButton<String>(
            isDense: true,
            hint: new Text("Select"),
            value: _mySelection,
            onChanged: (String newValue) 
              print (_mySelection);
            ,
            items: snapshot.data.documents.map((Map map) 
              return new DropdownMenuItem<String>(
                value: map["id"].toString(),
                child: new Text(
                  map["name"],
                ),
              );
            ).toList(),
        );,
        );
      

谢谢!

【问题讨论】:

删除类型提及 Map - snapshot.data.documents.map((Map map) to snapshot.data.documents.map((map) .... 【参考方案1】:
new StreamBuilder<QuerySnapshot>(
    stream: Firestore.instance.collection('categories').snapshots(),
    builder: (context, snapshot)
      if (!snapshot.hasData) return const Center(
        child: const CupertinoActivityIndicator(),
      );
      var length = snapshot.data.documents.length;
      DocumentSnapshot ds = snapshot.data.documents[length - 1];
      _queryCat = snapshot.data.documents;
      return new Container(
        padding: EdgeInsets.only(bottom: 16.0),
        width: screenSize.width*0.9,
        child: new Row(
          children: <Widget>[
            new Expanded(
                flex: 2,
                child: new Container(
                  padding: EdgeInsets.fromLTRB(12.0,10.0,10.0,10.0),
                  child: new Text("Category",style: textStyleBlueBold,),
                )
            ),
            new Expanded(
              flex: 4,
              child:new InputDecorator(
                decoration: const InputDecoration(
                  //labelText: 'Activity',
                  hintText: 'Choose an category',
                  hintStyle: TextStyle(
                    color: primaryColor,
                    fontSize: 16.0,
                    fontFamily: "OpenSans",
                    fontWeight: FontWeight.normal,
                  ),
                ),
                isEmpty: _category == null,
                child: new DropdownButton(
                  value: _category,
                  isDense: true,
                  onChanged: (String newValue) 
                    setState(() 
                      _category = newValue;
                      dropDown = false;
                      print(_category);
                    );
                  ,
                  items: snapshot.data.documents.map((DocumentSnapshot document) 
                    return new DropdownMenuItem<String>(
                        value: document.data['title'],
                        child: new Container(
                          decoration: new BoxDecoration(
                              color: primaryColor,
                              borderRadius: new BorderRadius.circular(5.0)
                          ),
                          height: 100.0,
                          padding: EdgeInsets.fromLTRB(10.0, 2.0, 10.0, 0.0),
                          //color: primaryColor,
                          child: new Text(document.data['title'],style: textStyle),
                        )
                    );
                  ).toList(),
                ),
              ),
            ),
          ],
        ),
      );
    
);

【讨论】:

我觉得还是加上cmets来帮助提问者理解比较好 如何添加文档ID为key,name为value?【参考方案2】:
StreamBuilder<QuerySnapshot>(  
    stream: Firestore.instance.collection('shops').snapshots(), builder: (context, snapshot) 
      if (!snapshot.hasData)
        return Center(
          child: CupertinoActivityIndicator(),
        );

      return Container(
        padding: EdgeInsets.only(bottom: 16.0),
        child: Row(
          children: <Widget>[
            Expanded(
                flex: 2,
                child: Container(
                  padding: EdgeInsets.fromLTRB(12.0, 10.0, 10.0, 10.0),
                  child: Text(
                    "Shop",
                  ),
                )),
            new Expanded(
              flex: 4,
              child: DropdownButton(
                value: shopId,
                isDense: true,
                onChanged: (valueSelectedByUser) 
                  _onShopDropItemSelected(valueSelectedByUser);
                ,
                hint: Text('Choose shop'),
                items: snapshot.data.documents
                    .map((DocumentSnapshot document) 
                  return DropdownMenuItem<String>(
                    value: document.data['plant_name'] +
                        ' ' +
                        document.data['shop_type'],
                    child: Text(document.data['plant_name'] +
                        ' ' +
                        document.data['shop_type']),
                  );
                ).toList(),
              ),
            ),
          ],
        ),
      );
    );

shopId 在构建函数之外定义。 那么onChanged的方法是:

  void _onShopDropItemSelected(String newValueSelected) 
    setState(() 
      this.shopId = newValueSelected;
    );
  

【讨论】:

以上是关于如何将 Firestore 文档列表绑定到 Flutter 中的下拉菜单?的主要内容,如果未能解决你的问题,请参考以下文章

我想将对象列表添加到 Firestore 文档,-颤动

如何在 Firestore 中获取生成的文档 ID,然后将子集合添加到其中?

将用户绑定到 Firestore 集合的正确方法?

使用 StreamBuilder 获取 Firestore 文档,其中包含颤动中的地图列表

如何使用 SwiftUI 将值数组写入 Firestore

React setState未在firestore中执行添加文档承诺解析