Flutter - How implement one E-Mail TextFormField widget for using in multiple screens?

Viewed 3025

I'm developing a app with a register, login and reset password screen. In all this screens the user must enter his e-mail address. Now i will not implement the e-mail address textfield for every single screen. So i will implement a email textfield widget for every screen like the code below.

import 'package:flutter/material.dart';
import 'package:email_validator/email_validator.dart';

class EMailTextFormField extends StatefulWidget {

  @override
  _EMailTextFormFieldState createState() => _EMailTextFormFieldState();
}

class _EMailTextFormFieldState extends State<EMailTextFormField> {
  final _email = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 3.0),
      child: TextFormField(
        decoration: InputDecoration(
          icon: Icon(Icons.email, size: IconTheme.of(context).size, color: IconTheme.of(context).color),
          labelText: 'E-Mail...',
          counterText: '',
        ),
        keyboardType: TextInputType.emailAddress,
        controller: _email,
        validator: _validateEmail,
        maxLength: 70,
      ),
    );
  }

  String _validateEmail(String email) {
    // validate E-Mail function...
  }
}

My problem is now that i can't use the TextEditingController (_email) outside this widget in the different screens (register, login and reset password) like this as a example:

final FirebaseUser user = (await _auth.createUserWithEmailAndPassword(
                  email: _email.text.toString(), password: _password.text.toString())).user;

The error is "Undefined name _email" because the _email TextEditingController is in the EMailTextFormField widget, but how can i give the value of the _email field from EMailTextFormField widget to the other screens (register, login and reset password)?

Can anyone help me i found so far no solution.

1 Answers

You can do this using onSaved callback.

EMailTextFormField:

class EMailTextFormField extends StatefulWidget {

  final void Function(String email) onSaved;

  const EMailTextFormField({Key key, this.onSaved}) : super(key: key);

  @override
  EMailTextFormFieldState createState() => EMailTextFormFieldState();
}

class EMailTextFormFieldState extends State<EMailTextFormField> {
  final _email = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 3.0),
      child: TextFormField(
        decoration: InputDecoration(
          icon: Icon(Icons.email, size: IconTheme.of(context).size, color: IconTheme.of(context).color),
          labelText: 'E-Mail...',
          counterText: '',
        ),
        keyboardType: TextInputType.emailAddress,
        controller: _email,
        validator: _validateEmail,
        maxLength: 70,
        onSaved: widget.onSaved, //callback
      ),
    );
  }

  String _validateEmail(String email) {
    // validate E-Mail function...
  }
}

Page where you will use EMailTextFormField:

class EmailPage extends StatefulWidget {
  EmailPage({Key key}) : super(key: key);

  @override
  _EmailPageState createState() => _EmailPageState();
}

class _EmailPageState extends State<EmailPage> {

  String _email;

  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Email Page'),
      ),
      body: Form(
        key: _formKey,
        child: Column(
          children: <Widget>[
            EMailTextFormField(
              onSaved: (String email) => _email = email,
            ),
            RaisedButton(
              child: Text('Go'),
              onPressed: (){
                if (_formKey.currentState.validate()) {
                  _formKey.currentState.save();

                  print(_email);
                }
              },
            )
          ],
        ),
      ),
    );
  }
}
Related