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

Posted

技术标签:

【中文标题】我想将对象列表添加到 Firestore 文档,-颤动【英文标题】:I want to add list of objects to firestore document, - flutter 【发布时间】:2020-06-07 13:58:26 【问题描述】:

我想将对象列表添加到 firestore 文档

我定义了产品数据模型

我也有分类数据模型

我想在 firestore 的产品文档中添加类别列表

我将类别添加到临时列表中,然后将值放入 product.categories product.categories = categorytemplist;

我使用了提供者状态

当我将产品保存到屏幕保持时,没有错误但没有保存

所有与产品形式相关的文件都在下面

    //product form dart file
import 'package:flutter/material.dart';
import '../api/categories_api.dart';
import '../models/category_model.dart';
import '../providers/category_provider.dart';
import '../api/products.dart';
import '../models/product_model.dart';
import '../providers/product_provider.dart';
import 'package:provider/provider.dart';

    class ProductForm extends StatefulWidget 
      final bool isUpdating;

      ProductForm(@required this.isUpdating);

      @override
      _ProductFormState createState() => _ProductFormState();
    

    class _ProductFormState extends State<ProductForm> 
      final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
      final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

      ProductModel _currentProduct;
      CategoryModel _categoryDropdownValue;
      List<CategoryModel> _categoryTempList=[];

      @override
      void initState() 
        super.initState();
        ProductProvider productProvider = Provider.of<ProductProvider>(context, listen: false);
        CategoryProvider categoryProvider = Provider.of<CategoryProvider>(context, listen: false);
          getCategories(categoryProvider);

        if (productProvider.currentProduct != null) 
          _currentProduct = productProvider.currentProduct;
         else 
          _currentProduct = new ProductModel();
        
      
      Widget _buildIdField() 
        return TextFormField(
          decoration: InputDecoration(labelText: 'Brand ID'),
          initialValue: _currentProduct.id,
          keyboardType: TextInputType.text,
          style: TextStyle(fontSize: 20),
          validator: (String value) 
            if (value.isEmpty) 
              return 'Product ID is required';
            

             return null;
          ,
          onSaved: (String value) 
            _currentProduct.id = value;
          ,
        );
      
      Widget _buildNameField() 
        return TextFormField(
          decoration: InputDecoration(labelText: 'Product name'),
          initialValue: _currentProduct.name,
          keyboardType: TextInputType.text,
          style: TextStyle(fontSize: 20),
          onSaved: (String value) 
            _currentProduct.name = value;
          ,
        );
      
      Widget _buildCategoryField() 
        CategoryProvider categoryProvider = Provider.of<CategoryProvider>(context);

        return DropdownButtonFormField<CategoryModel>(
              hint: Text('Select category'),
              value: _categoryDropdownValue,
              icon: Icon(Icons.arrow_downward),
              iconSize: 24,
              elevation: 16,
              style: TextStyle(color: Colors.deepPurple),

              onChanged: (CategoryModel newValue) 
                setState(() 
                  _categoryDropdownValue = newValue;
                );
              ,
              items: categoryProvider.categoryList.map<DropdownMenuItem<CategoryModel>>((CategoryModel value) 
                return DropdownMenuItem<CategoryModel>(
                  value: value,
                  child: Text(value.name), 
                   );
                  ).toList(),
              // onSaved: (CategoryModel value)
              //   _currentProduct.categories= _categoryTempList;
              //   print('save categories at dropdownmenu');
              // ,
         );
       

      _addCategories(CategoryModel category) 
        if (category!=null )
          setState(() 
              _categoryTempList.add(category);
          );
        
        
      _onProductUploaded(ProductModel product) 
        ProductProvider productProvider = Provider.of<ProductProvider>(context, listen: false);
        productProvider.addProduct(product);
        Navigator.pop(context);
      

      _saveProduct() 
        print('saveProduct Called');
        if (!_formKey.currentState.validate()) 
          return;
        

        _formKey.currentState.save();
        _currentProduct.categories= _categoryTempList ;
        print('form saved');

        uploadProduct(_currentProduct, widget.isUpdating, _onProductUploaded);
      

      @override
      Widget build(BuildContext context) 
        return Scaffold(
          key: _scaffoldKey,
          appBar: AppBar(title: Text('Product Form')),
          body: SingleChildScrollView(
            padding: EdgeInsets.all(32),
            child: Form(
              key: _formKey,
              autovalidate: true,
              child: Column(children: <Widget>[
                Text(
                  widget.isUpdating ? "Edit Product" : "Create Product",
                  textAlign: TextAlign.center,
                  style: TextStyle(fontSize: 30),
                ),
                SizedBox(height: 16),
            _buildIdField(),
                _buildNameField(),
                _buildCategoryField(),
             ButtonTheme(
                    child: RaisedButton(
                        child: Text('Add', style: TextStyle(color: Colors.white)),
                        onPressed: () => _addCategories(_categoryDropdownValue), 
                  ),),
                GridView.count(
                  shrinkWrap: true,
                  scrollDirection: Axis.vertical,
                  padding: EdgeInsets.all(8),
                  crossAxisCount: 3,
                  crossAxisSpacing: 4,
                  mainAxisSpacing: 4,
                  children: _categoryTempList
                      .map(
                        (CategoryModel value) => Card(
                          color: Colors.black54,
                          child: Center(
                            child: Text(
                              value.name,
                              style: TextStyle(color: Colors.white, fontSize: 14),
                            ),
                          ),
                        ),
                      )
                      .toList(),
                ),
              ]),
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () 
              FocusScope.of(context).requestFocus(new FocusNode());
              _saveProduct();
            ,
            child: Icon(Icons.save),
            foregroundColor: Colors.white,
          ),
        );
      
    

//产品数据模型dart文件

import 'package:cloud_firestore/cloud_firestore.dart';
import 'category_model.dart';
    class ProductModel
     static const ID = "id";
     static const NAME = "name";
     static const CATEGORIES= "categories";

     String id;
     String name;
     List<CategoryModel> categories;

    //  named constructure
    ProductModel();

    // deserialize data from firestore
      ProductModel.fromMap(Map<String, dynamic> data)
       id = data[ID];
       name = data[NAME];
       categories = data[CATEGORIES];
      

      Map<String, dynamic> toMap() 
        return 
          'ID': id,
          'NAME':name,
          'CATEGORIES': categories,  
        ;
      
    

// Category data model dart file
import 'package:cloud_firestore/cloud_firestore.dart';

    class CategoryModel
     static const ID = "id";
     static const NAME = "name";
     String id;
     String name;

    //  named constructure
    CategoryModel();

    // deserialize data from firestore
      CategoryModel.fromMap(Map<String, dynamic> data)
       id = data[ID];
       name = data[NAME];
        

      Map<String, dynamic> toMap() 
        return 
          'ID': id,
          'NAME':name,
        ;
      
    


// Product provider dart file
import '../models/product_model.dart';
import 'package:flutter/material.dart';

    class ProductProvider with ChangeNotifier 
      List<ProductModel> _productList=[];
      ProductModel _currentProduct;
      List<ProductModel> _featuredProductList=[];



    //  getter
      List<ProductModel> get productList => _productList;
      List<ProductModel> get featuredProductList => _featuredProductList;
      ProductModel get currentProduct => _currentProduct;


    //  setter
      set productList(List<ProductModel> productList) 
        _productList = productList;
        notifyListeners();
      

       set currentProduct(ProductModel product) 
        _currentProduct = product;
        notifyListeners();
      

       addProduct(ProductModel product) 
        _productList.insert(0, product);
        notifyListeners();
      

      deleteProduct(ProductModel product) 
        _productList.removeWhere((_product) => _product.id == product.id);
        notifyListeners();
      

    

// 类别提供者 dart 文件

import '../models/category_model.dart';
import 'package:flutter/material.dart';

class CategoryProvider with ChangeNotifier 
  List<CategoryModel> _categoryList=[];
  CategoryModel _currentCategory;
  List<CategoryModel> _featuredCategoryList=[];


//  getter
  List<CategoryModel> get categoryList => _categoryList;
  List<CategoryModel> get featuredCategoryList => _featuredCategoryList;
  CategoryModel get currentCategory => _currentCategory;


//  setter
  set categoryList(List<CategoryModel> categoryList) 
    _categoryList = categoryList;
    notifyListeners();
  

   set featuredCategoryList(List<CategoryModel> featuredCategoryList) 
    _featuredCategoryList = featuredCategoryList;
    notifyListeners();
  

   set currentCategory(CategoryModel category) 
    _currentCategory = category;
    notifyListeners();
  

   addCategory(CategoryModel category) 
    _categoryList.insert(0, category);
    notifyListeners();
  

  deleteCategory(CategoryModel category) 
    _categoryList.removeWhere((_category) => _category.id == category.id);
    notifyListeners();
  


// 产品 api dart 文件 - firestore

import 'package:cloud_firestore/cloud_firestore.dart';
import '../providers/product_provider.dart';
import '../models/product_model.dart';

getProducts(ProductProvider productProvider) async
  QuerySnapshot snapshot= await Firestore.instance.collection('products').getDocuments();
  List<ProductModel> _productList=[];
  snapshot.documents.forEach((document)
    ProductModel product= ProductModel.fromMap(document.data);
    _productList.add(product);
  );
  productProvider.productList=_productList;


uploadProduct(ProductModel product, bool isUpdating, Function productUploaded, String imageUrl) async 
  CollectionReference productRef = Firestore.instance.collection('products');

  if (imageUrl != null) 
    product.picture = imageUrl;
  

  if (isUpdating) 
    await productRef.document(product.id).updateData(product.toMap());
    productUploaded(product);
    print('updated product with id: $product.id');
   else 

    DocumentReference documentRef = await productRef.add(product.toMap());
    product.id = documentRef.documentID;
    print('uploaded successfully: $product.toString()');
    await documentRef.setData(product.toMap(), merge: true);
    productUploaded(product);
  


deleteProduct(ProductModel product, Function productDeleted) async 
  await Firestore.instance.collection('products').document(product.id).delete();
  productDeleted(product);

【问题讨论】:

您好,我对 Firestone 了解不多,但一种可能性是看看它是否有任何长度或类似于 html 中的活动的模块,称为 >> 我希望这个参考可以帮助你 嗨!请在问题中格式化您的代码并添加更多详细信息。您是否将每个对象序列化为 json? @Sebastian 我添加了文件 嗨,你确定这是代码的工作版本吗?我试图将它复制粘贴到我的 IDE 以便于阅读,它显示了很多错误...(我还导入了 package:flutter/material.dartpackage:provider/provider.dart 【参考方案1】:

我终于找到了在产品数据模型中将对象列表添加到 Firestore 中的文档的方法,它解决了问题: 'categories': categories.map((i) => i.toMap()).toList(),

ProductModel
String id;
String name;
List<CategoryModel> categories

ProductModel.fromMap(Map<String, dynamic> data)
   id = data['id'];
   name= data['name'];
   categories = data['categories']; // here there is a problem, as i can't get product document with list of objects but i am working on it 

Map<String, dynamic> toMap() 
    return 
      'id': id,
      'name':name,
      'categories': categories.map((i) => i.toMap()).toList(),  // this worked well

;

CategoryModel
String id;
String name;

CategoryModel.fromMap(Map<String, dynamic> data)
   id = data['id'];
   name= data['name'];

Map<String, dynamic> toMap() 
    return 
      'id': id,
      'name':name,
;

【讨论】:

要解决您无法获取包含对象列表的产品文档的问题,请在您的 ProductModel 类中更改 ProductModel.fromMap(),如下所示:ProductModel.fromMap(Map&lt;String, dynamic&gt; data) id = data['id']; name= data['name']; categories = data['categories'].map&lt;CategoryModel&gt;((mapString) =&gt; CategoryModel.fromMap(mapString)).toList(), 【参考方案2】:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:equatable/equatable.dart';

import 'package:flutter/material.dart';

class Cart extends Equatable 
final String id;
final String date;
final Customer customer;
final List<Product> products;
final int isVisible;

Cart(
    this.id,
    @required this.date,
    @required this.customer,
    @required this.products,
    this.isVisible = 1);


static Cart fromJson(Map<String, Object> json) 
    return Cart (
    id: json['id'] as String,
    date: json['date'] as String,
    customer: Customer.fromJson(json['customer']),
    products: json['products'] as List,
    isVisible: json['isVisible'] as int,
    );


Map<String, Object> toJson() 
    return 
      'id': id,
      'date': date,
      'customer': customer.toJson(),
      'products': products.map((p) => p.toJson()).toList(), 
      'isVisible': isVisible,
    ;
  

static Cart fromSnapshot(QueryDocumentSnapshot snap) 
    return Cart(
    id: snap.id,
    date: snap.get('date'),
    customer: Customer.fromJson(snap.get('customer')),
    products: snap
        .get('products')
        .map<Product>((p) => Product.fromJson(p))
        .toList(),   // map product array to list
    isVisible: snap.get('isVisible'),
    );


Map<String, Object> toDocument() 
    return 
    'id': id,
    'date': date,
    'customer': customer.toJson(),
    'products': products.map((p) => p.toJson()).toList(), // convert product list to map object
    'isVisible': isVisible,
    ;


@override
List<Object> get props =>
    [id, date, isVisible, customer, products];

@override
bool get stringify => true;

【讨论】:

【参考方案3】:

要在 firestore 中的文档中添加和读取对象列表,这里是一个简单的 ProductModel,带有列表对象 CategoryModel。

ProductModel
    String id;
    String name;
    List<CategoryModel> categories

    ProductModel.fromMap(Map<String, dynamic> data)
        id = data['id'];
        name= data['name'];
        categories = data['categories'].map<CategoryModel>((mapString) =>  
                  CategoryModel.fromMap(mapString)).toList(), //// this 
       ////worked well to read from firestore
    
    Map<String, dynamic> toMap() => 
            'id': id,
            'name':name,
            'categories': categories.map((i) => i.toMap()).toList(),   
            //this worked well to add to firestore

       ;
    


CategoryModel
    String id;
    String name;

    CategoryModel.fromMap(Map<String, dynamic> data)
       id = data['id'];
       name= data['name'];
    
    Map<String, dynamic> toMap() =>
      
          'id': id,
          'name':name,
      ;
    
                                                                                                                                                                         

【讨论】:

以上是关于我想将对象列表添加到 Firestore 文档,-颤动的主要内容,如果未能解决你的问题,请参考以下文章

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

Firestore - 节省文档读取费用

如何向云 Firestore 中的对象添加新属性 [重复]

如何将地图存储到 Firestore 数组

Flutter firestore - 检查文档ID是不是已经存在

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