title: Upload Form to Firestore with Flutter
body: <p>I'm confused about how to upload a form to Firestore in my flutter app.  I've gone through numerous tutorials and am able to login to Firebase and retrieve data from Firestore into my flutter app, but I can't figure out how to upload a Form with numerous Textfields to Firestore. </p>
  
  <p>Example:  Document title "books"
  Textfields would include:  Title, Author, etc. </p>
  
  <p>***  // Below is my page which does import data from Firestore (This works).  I've added a button which goes to another page where I've attempted to add a form to upload to Firestore (This doesn't work).  The loading of the page works, but uploading to Firestore is not set up.  </p>
  
  <pre><code>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: &lt;Widget&gt;[
  
            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&lt;QuerySnapshot&gt; 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) =&gt; new UploadFormField()),
          );
  
        }
      )
        );
        }
  
  } 
  
  
  
  // UPLOAD TO FIRESTORE
  
  
  
  class UploadFormField extends StatefulWidget {
    @override
    _UploadFormFieldState createState() =&gt; _UploadFormFieldState();
  }
  
  class _UploadFormFieldState extends State&lt;UploadFormField&gt; {
    GlobalKey&lt;FormState&gt; _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: &lt;Widget&gt;[
          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;
              });
      }
  
    }
  }
  </code></pre>