我想将对象列表添加到firestore文档
我定义了产品数据模型
我还有分类数据模型
我想将类别列表添加到firestore 中的产品文档中
我将类别添加到临时列表中,然后将值放在产品中。类别product.cacategories=类别临时列表;
我使用了提供商状态
当我将产品保存到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中的文档添加对象列表的方法,它解决了问题:
"类别":类别.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,
};}}
要在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,
};
}
}
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;
}