TJMitch95
TJMitch95

Reputation: 491

Flutter and Firebase - Collect additional data on sign up

I am using the method createUserWithEmailAndPassword but would like to collect more data when a user signs up. In addition to email and password I would also like to collect:

Here is my auth services code:

    //Email & Password Sign Up
  Future<String> createUserWithEmailAndPassword(
      String email, String password,
      ) async {
    final authResult = await _firebaseAuth.createUserWithEmailAndPassword(
        email: email,
        password: password,
    );

    // Update the username
    await updateUserName(email, authResult.user);
    return authResult.user.uid;

  }

and my sign up page:

import 'package:easy_tiger/constants/appbar.dart';
import 'package:easy_tiger/screens/account.dart';
import 'package:easy_tiger/style.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:easy_tiger/services/auth_service.dart';

enum AuthFormType { signIn, signUp }

class SignUpPage extends StatefulWidget {
  final AuthFormType authFormType;

  SignUpPage({Key key, this.authFormType}) : super(key: key);

  @override
  _SignUpPageState createState() => _SignUpPageState(authFormType: this.authFormType);
}

class _SignUpPageState extends State<SignUpPage> {
  AuthFormType authFormType;


  _SignUpPageState({this.authFormType});

  final formKey = GlobalKey<FormState>();
  String _firstName,
      _lastName,
      _email,
      _confirmEmail,
      _password,
      _confirmPassword,
      _dateOfBirth;

  bool validate(){
    final form = formKey.currentState;
    form.save();
    if(form.validate()){
      form.save();
      return true;
    } else {
      return false;
    }
  }
  void switchFormState(String state) {
    formKey.currentState.reset();
    formKey.currentState.validate();
    if(state == 'signUp') {
      setState(() {
        authFormType = AuthFormType.signUp;
      });
    } else {
      setState(() {
        authFormType = AuthFormType.signIn;
      });
    }
  }

  void submit() async {
    if (validate()) {
      try {
        final auth = Provider
            .of(context)
            .auth;
        if (authFormType == AuthFormType.signIn) {
          String uid = await auth.signInWithEmailAndPassword(_email, _password);
          print("Signed In with ID $uid");
          Navigator.of(context).pushReplacementNamed('/home');
        } else {
          String uid = await auth.createUserWithEmailAndPassword(
              _email,
              _password,);
          print("Signed up with New ID $uid");
          Navigator.of(context).pushReplacementNamed('/home');
        }
      } catch (e) {
        print(e);
      }
    }
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: PreferredSize(
            preferredSize: const Size.fromHeight(80),
            child: MainAppBar(
              text: buildAppBarText(),
            )),
        body: SingleChildScrollView(
          child: Padding(
            padding: const EdgeInsets.all(12.0),
            child: Center(
              child: Container(
                child: Column(
                  children: <Widget>[
                    Align(
                      child: Text(buildTitleText(), style: AppBarTextStyle),
                    ),
                    Container(
                      padding: EdgeInsets.only(top: 10),
                    ),
                    Padding(
                      padding: const EdgeInsets.all(20.0),
                      child: Form(
                          key: formKey,
                          child: Column(
                            children: buildInputs() + buildSwitchText(),
                          )),
                    ),
                  ],
                ),
              ),
            ),
          ),
        ));
  }

  buildHeaderText() {
    String _headerText;
    if (authFormType == AuthFormType.signUp) {
      _headerText = "Don't have an account?";
    } else {
      _headerText = "Already have an account?";
    } return _headerText;
  }

  List<Widget> buildInputs() {
    List<Widget> textFields = [];

    if (authFormType == AuthFormType.signIn) {
      textFields.add(TextFormField(
        style: TextStyle(
          fontSize: 12.0,
        ),
        decoration: buildSignUpInputDecoration('Email'),
        validator: EmailValidator.validate,
        onSaved: (value) => _email = value
      ));
      textFields.add(SizedBox(
        height: 15,
      ));
      textFields.add(TextFormField(
    style: TextStyle(
    fontSize: 12.0,
    ),
    decoration: buildSignUpInputDecoration('Password'),
    obscureText: true,
    validator: PasswordValidator.validate,
    onSaved: (value) => _password = value,
    ),);
    }
    else {
        textFields.clear();
      //if we're in the sign up state, add name
      // add email & password
      textFields.add(TextFormField(
      style: TextStyle(
      fontSize: 12.0,
      ),
      decoration: buildSignUpInputDecoration('First Name'),
      onSaved: (value) => _firstName,
      ));
      textFields.add(SizedBox(
        height: 15,
      ));
      textFields.add(TextFormField(
    style: TextStyle(
    fontSize: 12.0,
    ),
    decoration: buildSignUpInputDecoration('Last Name'),
    onSaved: (value) => _lastName,
    ));
      textFields.add(SizedBox(
        height: 15,
      ));
      textFields.add(TextFormField(
    style: TextStyle(
    fontSize: 12.0,
    ),
    decoration: buildSignUpInputDecoration('Email Address'),
    onSaved: (value) => _email,
    ));
      textFields.add(SizedBox(
        height: 15,
      ));
      textFields.add(TextFormField(
    style: TextStyle(
    fontSize: 12.0,
    ),
    decoration: buildSignUpInputDecoration('Confirm Email Address'),
    onSaved: (value) => _confirmEmail,
    ));
      textFields.add(SizedBox(
        height: 15,
      ));
      textFields.add(TextFormField(
    style: TextStyle(
    fontSize: 12.0,
    ),
    decoration: buildSignUpInputDecoration('Password'),
    obscureText: true,
    onSaved: (value) => _password,
    ));
      textFields.add(SizedBox(
        height: 15,
      ));
      textFields.add(TextFormField(
    style: TextStyle(
    fontSize: 12.0,
    ),
    decoration: buildSignUpInputDecoration('Confirm Password'),
    onSaved: (value) => _confirmPassword,
    ));
      textFields.add(SizedBox(
        height: 15,
      ));
      textFields.add(TextFormField(
    style: TextStyle(
    fontSize: 12.0,
    ),
    decoration: buildSignUpInputDecoration('Date of Birth'),
    onSaved: (value) => _dateOfBirth,
    ));
      textFields.add(SizedBox(
        height: 15,
      ));
    }
      return textFields;
  }

  List<Widget> buildSwitchText() {
    String _switchButtonTextPart1, _switchButtonTextPart2,_newFormState;

    if(authFormType == AuthFormType.signIn) {
      _switchButtonTextPart1 = "Haven't got an account? ";
      _switchButtonTextPart2 = 'Sign Up';
      _newFormState = 'signUp';
    } else {
      _switchButtonTextPart1 = 'Already have an account? ';
      _switchButtonTextPart2 = 'Sign In';
      _newFormState = 'signIn';
    } return [
      SizedBox(height: 5.0),
      Container(
        width: MediaQuery.of(context).size.height * 0.7,
        child: RaisedButton(
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0),),
            color: kPrimaryColor,
            textColor: Colors.black,
            child: Padding(
              padding: const EdgeInsets.all(8.0),
              child: Text(buildTitleText(),
              style: TextStyle(fontFamily: FontNameDefault,
              fontSize: 15.0),),
            ),
            onPressed: submit),
      ),
      SizedBox(height: 5.0,),
    RichText(
      text: TextSpan(
          style: TextStyle(
            fontFamily: FontNameDefault,
            color: Colors.black,
            fontSize: 12.0,
          ),
          children: <TextSpan>[
            TextSpan(
              text: _switchButtonTextPart1
            ),
            TextSpan(
                text: _switchButtonTextPart2,
                style: TextStyle(
                    decoration: TextDecoration.underline,
                    color: Colors.black,
                    fontSize: 12.0),
                recognizer: TapGestureRecognizer()
                  ..onTap = () {
                    switchFormState(_newFormState);
                  })
          ]),
    ),
    ];
  }

  String buildAppBarText() {
    String _switchAppBarHeader;

    if(authFormType == AuthFormType.signIn) {
      _switchAppBarHeader = "Already have an account?";
    } else {
      _switchAppBarHeader = "Don't have an account?";
    } return
        _switchAppBarHeader;
  }

  String buildTitleText() {
    String _switchTextHeader;

    if(authFormType == AuthFormType.signIn) {
      _switchTextHeader = "Sign In";
    } else {
      _switchTextHeader = "Sign Up";
    } return
      _switchTextHeader;
  }


}
class AccountController extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final AuthService auth = Provider.of(context).auth;
    return StreamBuilder(
        stream: auth.onAuthStateChanged,
        builder: (context, AsyncSnapshot<String> snapshot) {
          if (snapshot.connectionState == ConnectionState.active) {
            final bool signedIn = snapshot.hasData;
            return signedIn ? SignInPage() : SignUpPage();
          }
          return CircularProgressIndicator();
        });
  }
}

InputDecoration buildSignUpInputDecoration(String hint) {
  return InputDecoration(
    isDense: true,
    fillColor: Colors.white,
    hintText: hint,
    filled: true,
    enabledBorder: OutlineInputBorder(
      borderSide: BorderSide(width: 0.0),
    ),
    contentPadding: const EdgeInsets.only(left: 14.0, bottom: 10.0, top: 10.0),
  );
}

class Provider extends InheritedWidget {
  final AuthService auth;

  Provider({Key key, Widget child, this.auth}) : super(key: key, child: child);

  @override
  bool updateShouldNotify(InheritedWidget oldWidget) {
    return true;
  }

  static Provider of(BuildContext context) =>
      context.dependOnInheritedWidgetOfExactType<Provider>();
}

Can someone advise the best way to go about achieving this thanks.

Upvotes: 2

Views: 1619

Answers (2)

TJMitch95
TJMitch95

Reputation: 491

Managed to work out a solution...

In my signup screen I imported cloud_firestore:

import 'package:cloud_firestore/cloud_firestore.dart';

I then altered the following to use the uid we create to create a document and set the fields equal to the values passed:

 if (validate()) {
      try {
        final auth = Provider
            .of(context)
            .auth;
        if (authFormType == AuthFormType.signIn) {
          String uid = await auth.signInWithEmailAndPassword(_email, _password);
          print("Signed In with ID $uid");
          Navigator.of(context).pushReplacementNamed('/home');
        } else {
          String uid = await auth.createUserWithEmailAndPassword(
              _email,
              _password,);
          userCollection.document(uid).setData({
            'First Name' : _firstName,
            'Last Name' : _lastName,
            'Date of Birth' : _dateOfBirth
          });
          print("Signed up with New ID $uid");
          Navigator.of(context).pushReplacementNamed('/home');
        }
      } catch (e) {
        print(e);
      }

I had to remove my validation method as it was causing issues. Ran the new code and a new user appeared in my database.

Upvotes: 4

DAMMAK
DAMMAK

Reputation: 179

you will save the addition data inside your firestore e.g(firstname, lastname, date of birth) and add extra field for user id which will identify/mapped/linked the user with the firebaseAuth data

you will get the data(uid) from the AuthResult.user object.

Upvotes: 0

Related Questions