我对如何在Flutter应用程序中将表单上载到Firestore感到困惑。我已经完成了许多教程,并且能够登录Firebase并将数据从Firestore检索到我的flutter应用程序中,但是我不知道如何将具有大量Textfields的表单上载到Firestore。
示例:文档标题“书籍” 文本字段将包括:标题,作者等。
*** //下面是我的页面,该页面确实从Firestore导入数据(有效)。我添加了一个按钮,该按钮转到另一个页面,试图在其中添加要上传到Firestore的表单(这不起作用)。该页面的加载有效,但未设置上传到Firestore。
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'dart:async';
class FireStore extends StatelessWidget {
FireStore({this.auth, this.onSignedOut});
final BaseAuth auth;
final VoidCallback onSignedOut;
void _signOut () async {
try {
await auth.signOut();
onSignedOut();
} catch (e) {
print (e);
}
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text ('Welcome'),
actions: <Widget>[
new FlatButton(
child: new Text('Logout', style: new TextStyle(fontSize: 17.0, color: Colors.white)),
onPressed: _signOut
)
]
),
body: new StreamBuilder(
stream: Firestore.instance.collection('books').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return CircularProgressIndicator();
return new GridView.count(
crossAxisCount: 2,
childAspectRatio: 1.0,
padding: const EdgeInsets.all(4.0),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
children: snapshot.data.documents.map((DocumentSnapshot document) {
return new ListTile(
title: new Text(document['title']),
subtitle: new Text(document['author']),
);
}).toList(),
);
},
),
floatingActionButton: new FloatingActionButton(
elevation: 0.0,
child: new Icon(Icons.add),
backgroundColor: new Color(0xFFE57373),
onPressed: (){
Navigator.push(
context,
new MaterialPageRoute(builder: (context) => new UploadFormField()),
);
}
)
);
}
}
// UPLOAD TO FIRESTORE
class UploadFormField extends StatefulWidget {
@override
_UploadFormFieldState createState() => _UploadFormFieldState();
}
class _UploadFormFieldState extends State<UploadFormField> {
GlobalKey<FormState> _key = GlobalKey();
bool _validate = false;
String title, author;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: new Text('Upload'),
),
body: new SingleChildScrollView(
child: new Container(
margin: new EdgeInsets.all(15.0),
child: new Form(
key: _key,
autovalidate: _validate,
child: FormUI(
)),
),
),
),
);
}
Widget FormUI() {
return new Column(
children: <Widget>[
new TextFormField(
decoration: new InputDecoration(hintText: 'Title'),
validator: validateTitle,
onSaved: (String val) {
title = val;
}
),
new TextFormField(
decoration: new InputDecoration(hintText: 'Author'),
validator: validateAuthor,
onSaved: (String val) {
author = val;
}
),
new SizedBox(height: 15.0),
new RaisedButton(onPressed: _sendToServer, child: new Text('Upload'),
)
],
);
}
String validateTitle (String value) {
String pattern = r' (^[a-zA-Z ]*$)';
RegExp regExp = new RegExp(pattern);
if (value.length == 0){
return 'Title is required';
} else if (!regExp.hasMatch(value)) {
return "Title must be a-z and A-Z";
}
return null;
}
String validateAuthor (String value) {
String pattern = r' (^[a-zA-Z ]*$)';
RegExp regExp = new RegExp(pattern);
if (value.length == 0){
return 'Author is required';
} else if (!regExp.hasMatch(value)) {
return "Author must be a-z and A-Z";
}
return null;
}
_sendToServer(){
if (_key.currentState.validate() ){
//No error in validator
_key.currentState.save();
print ("Title $title");
print ("Author $author");
} else {
// validation error
setState(() {
_validate = true;
});
}
}
}
答案 0 :(得分:0)
Flutter的Firestore插件将Map用作setData或添加函数的输入,因此无论您在类对象或其他变量中拥有什么数据,您都只需将其转换为map(或为嵌套数据结构使用嵌套map)并将其提供给setData或add函数作为输入保存在Firestore中。对于类,Flutter示例显示了大多数在类中实现的“ toMap()”函数,这些函数仅返回所需地图结构中所有数据类对象具有的对象,以及其对应的“ fromMap(Map mapData)”(用于从中创建对象)稍后从Firestore中获取数据时进行映射。
例如。
await Firestore.instance
.collection(TBL_USERS)
.add({
"type": "Dog",
"age": 6,
"breed": "abc",
});
或者因为它的地图,您可以直接使用任何字符串(只要它在地图中是唯一的)作为键
例如。
await Firestore.instance
.collection(TBL_USERS)
.add({
"Dog": {
"age": 6,
"breed": "abc",
},
"Cat" : {
"age": 2,
"breed": "xyz",
},
});
答案 1 :(得分:0)
我可以通过以下方法解决此问题:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'dart:async';
class FireStore extends StatelessWidget {
FireStore({this.auth, this.onSignedOut});
final BaseAuth auth;
final VoidCallback onSignedOut;
void _signOut () async {
try {
await auth.signOut();
onSignedOut();
} catch (e) {
print (e);
}
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text ('Welcome'),
actions: <Widget>[
new FlatButton(
child: new Text('Logout', style: new TextStyle(fontSize: 17.0, color: Colors.white)),
onPressed: _signOut
)
]
),
body: new StreamBuilder(
stream: Firestore.instance.collection('books').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return CircularProgressIndicator();
return new GridView.count(
crossAxisCount: 2,
childAspectRatio: 1.0,
padding: const EdgeInsets.all(4.0),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
children: snapshot.data.documents.map((DocumentSnapshot document) {
return new ListTile(
title: new Text(document['title']),
subtitle: new Text(document['author']),
);
}).toList(),
);
},
),
floatingActionButton: new FloatingActionButton(
elevation: 0.0,
child: new Icon(Icons.add),
backgroundColor: new Color(0xFFE57373),
onPressed: (){
Navigator.push(
context,
new MaterialPageRoute(builder: (context) => new UploadFormField()),
);
}
)
);
}
}
// UPLOAD TO FIRESTORE
class UploadFormField extends StatefulWidget {
@override
_UploadFormFieldState createState() => _UploadFormFieldState();
}
class _UploadFormFieldState extends State<UploadFormField> {
GlobalKey<FormState> _key = GlobalKey();
bool _validate = false;
String title, author;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: new Text('Upload'),
),
body: new SingleChildScrollView(
child: new Container(
margin: new EdgeInsets.all(15.0),
child: new Form(
key: _key,
autovalidate: _validate,
child: FormUI(),
),
),
),
),
);
}
Widget FormUI() {
return new Column(
children: <Widget>[
new TextFormField(
decoration: new InputDecoration(hintText: 'Title'),
validator: validateTitle,
onSaved: (String val) {
title = val;
}
),
new TextFormField(
decoration: new InputDecoration(hintText: 'Author'),
validator: validateAuthor,
onSaved: (String val) {
author = val;
}
),
new SizedBox(height: 15.0),
new RaisedButton(onPressed: _sendToServer, child: new Text('Upload'),
)
],
);
}
String validateTitle(String value) {
String patttern = r'(^[a-zA-Z ]*$)';
RegExp regExp = new RegExp(patttern);
if (value.length == 0) {
return "Title is Required";
} else if (!regExp.hasMatch(value)) {
return "Title must be a-z and A-Z";
}
return null;
}
String validateAuthor(String value) {
String patttern = r'(^[a-zA-Z ]*$)';
RegExp regExp = new RegExp(patttern);
if (value.length == 0) {
return "Author is Required";
} else if (!regExp.hasMatch(value)) {
return "Author must be a-z and A-Z";
}
return null;
}
_sendToServer(){
if (_key.currentState.validate() ){
//No error in validator
_key.currentState.save();
Firestore.instance.runTransaction((Transaction transaction) async {
CollectionReference reference = Firestore.instance.collection('books');
await reference.add({"Title": "$title", "Author": "$author"});
});
} else {
// validation error
setState(() {
_validate = true;
});
}
}
}