How to bind a Firestore documents list to a Dropdo

2020-03-26 05:38发布

问题:

I'm having a problem regarding dropdown menus and firestore, how can I bind a list of documents retrieved from firestore to a DropdownButton? Currently I'm having this error:

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

Code from my widget .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(),
        );},
        );
      }
}

Thanks!

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


回答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 is defined outside the build function. Then the method for onChanged is:

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