title: Text fields with validation in the Flutter BLoC library
body: <p>I am trying to learn the BLoC pattern in Flutter, but I just don't get it. I followed a tutorial on Udemy from which I generated the following code for a simple login form:</p>
  <p><code>BLoC Class</code></p>
  <pre><code>import 'dart:async';
  
  import 'package:login_bloc/src/blocs/validators.dart';
  
  class LoginBloc extends Validators {
    final _email = StreamController&lt;String&gt;();
    final _password = StreamController&lt;String&gt;();
  
    // Return Stream data
    // Streams are run thru validator first
    Stream&lt;String&gt; get getEmail =&gt; _email.stream.transform(validateEmail);
    Stream&lt;String&gt; get getPassword =&gt; _password.stream.transform(validatePassword);
  
    // Change data on stream
    Function(String) get changeEmail =&gt; _email.sink.add;
    Function(String) get changePassword =&gt; _password.sink.add;
  
    // Named by convention. Quiets Dart warning.
    dispose() {
      _email.close();
      _password.close();
    }
  }
  </code></pre>
  <p><code>UI Class</code></p>
  <pre><code>import 'package:flutter/material.dart';
  import 'package:login_bloc/src/blocs/login_bloc.dart';
  import 'package:login_bloc/src/providers/provider.dart';
  
  class LoginScreen extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      final loginBloc = Provider.of(context);
      return Padding(
        padding: const EdgeInsets.all(16.0),
        child: SafeArea(
          child: Column(
            children: &lt;Widget&gt;[
              emailField(loginBloc),
              passwordField(loginBloc),
              SizedBox(height: 10.0),
              submitButton(),
            ],
          ),
        ),
      );
    }
  
    Widget emailField(LoginBloc loginBloc) {
      return StreamBuilder&lt;Object&gt;(
          stream: loginBloc.getEmail,
          builder: (context, snapshot) {
            return TextField(
              keyboardType: TextInputType.emailAddress,
              decoration: InputDecoration(
                hintText: 'you@example.com',
                labelText: 'Email Address',
                errorText: snapshot.error,
              ),
              onChanged: loginBloc.changeEmail,
            );
          });
    }
  
    Widget passwordField(LoginBloc loginBloc) {
      return StreamBuilder&lt;Object&gt;(
          stream: loginBloc.getPassword,
          builder: (context, snapshot) {
            return TextField(
              obscureText: true,
              keyboardType: TextInputType.text,
              decoration: InputDecoration(
                labelText: 'Password',
                errorText: snapshot.error,
              ),
              onChanged: loginBloc.changePassword,
            );
          });
    }
  
    Widget submitButton() {
      return RaisedButton(
        child: Text(
          'Login',
          style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
        ),
        color: Colors.blue,
        onPressed: () =&gt; {},
      );
    }
  }
  
  </code></pre>
  <p>The validators are super simple: basically the email needs an '@' sign and the password has to be more than 4 chars. It makes sense as I follow along, but as soon as I try to implement on my own, it goes fuzzy. So, as part of my learning, I wanted to try and convert this simple login form to utilize the BLoC and Flutter_BLoC libraries, thinking it would abstract away some of the complexity and be easier to understand.</p>
  <p>After substantial work, I still can't figure out how to specify what state I'm trying to hold, and what events I'm trying to pass. I've run out of tutorials to view on YouTube and they nearly all use the counter app as an example with a single INT variable type. It's also complicated by the fact that the library just had a HUGE overhaul, and nearly all the tutorials are now outdated.</p>
  <p>Are there any examples available of how to do this using the v6 library? In particular, I am interested in how to activate the submit button only when both fields have been validated.</p>