我想将对象列表添加到 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.dart
和 package: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<String, dynamic> data) id = data['id']; name= data['name']; categories = data['categories'].map<CategoryModel>((mapString) => 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,然后将子集合添加到其中?