我想将对象列表添加到 firestore 文档中,- flutter

I want to add list of objects to firestore document, - flutter

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

我定义了产品数据模型

我也有类别数据模型

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

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

我使用了提供商状态

当我保存产品以 firestore 屏幕保持时,没有错误但它没有保存

所有与产品形式相关的文件如下

    //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);
}

我终于找到了在产品数据模型中向 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,
};}}
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;
}

要在 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,
      };
    }
}