How to implement validation with keyboard done button Flutter, observable, streamBuilder

693

You can wrap Your Password streamBuilder with another streamBilder and onSubmitted call submit method.

Widget passwordField(Bloc bloc) {
    return StreamBuilder(
        stream: bloc.submitValid,
        builder: (context, snap) {
          return StreamBuilder(
        stream: bloc.password,
        builder: (context, snapshot) {
          return TextField(
            obscureText: true,
            onChanged: bloc.changePassword,
            decoration: InputDecoration(
              hintText: 'Password',
              labelText: 'Password',
              errorText: snapshot.error,
            ),
            textInputAction: TextInputAction.done,
            onSubmitted: snap.hasData ? bloc.submit : null,
          );
        });
     });
  }
Share:
693
user12208004
Author by

user12208004

Updated on December 18, 2022

Comments

  • user12208004
    user12208004 over 1 year

    I'm building an app with Flutter and Bloc like architecture. I'm trying to call submit func with not only login button but also keyboard done button with password; only when email and password are valid.

    I could implement login button version with combineLatest, but I'm not sure keyboard version. I need to validate both email and password when keyboard done button pressed before calling submit. I could nest streamBuilder, but I feel it is not good practice.

    Is there any way to get the latest value from combineLatest? BehaviorSubject<bool>().value Or any possible advice to implement this.

    sample code:

    
          final _emailController = BehaviorSubject<String>();
          final _passwordController = BehaviorSubject<String>();
    
          // Add data to stream
          Stream<String> get email => _emailController.stream.transform(validateEmail);
          Stream<String> get password =>
              _passwordController.stream.transform(validatePassword);
    
          Stream<bool> get submitValid =>
              Observable.combineLatest2(email, password, (e, p) => true);
    
          // change data
          Function(String) get changeEmail => _emailController.sink.add;
          Function(String) get changePassword => _passwordController.sink.add;
    
          submit() {
            final validEmail = _emailController.value;
            final validPassword = _passwordController.value;
    
            print('Email is $validEmail, and password is $validPassword');
          }
    
    
    
        import 'package:flutter/material.dart';
        import '../blocs/bloc.dart';
        import '../blocs/provider.dart';
    
        class LoginScreen extends StatelessWidget {
          @override
          Widget build(BuildContext context) {
            final bloc = Provider.of(context);
    
            return Container(
              margin: EdgeInsets.all(20.0),
              child: Column(
                children: <Widget>[
                  emailField(bloc),
                  passwordField(bloc),
                  Container(
                    margin: EdgeInsets.only(top: 25.0),
                  ),
                  submitButton(bloc),
                ],
              ),
            );
          }
    
          Widget emailField(Bloc bloc) {
            return StreamBuilder(
              stream: bloc.email,
              builder: (context, snapshot) {
                return TextField(
                  onChanged: bloc.changeEmail,
                  keyboardType: TextInputType.emailAddress,
                  decoration: InputDecoration(
                    hintText: '[email protected]',
                    labelText: 'Email Address',
                    errorText: snapshot.error,
                  ),
                );
              },
            );
          }
    
          Widget passwordField(Bloc bloc) {
            return StreamBuilder(
                stream: bloc.password,
                builder: (context, snapshot) {
                  return TextField(
                    obscureText: true,
                    onChanged: bloc.changePassword,
                    decoration: InputDecoration(
                      hintText: 'Password',
                      labelText: 'Password',
                      errorText: snapshot.error,
                    ),
                    textInputAction: TextInputAction.done,
                    onSubmitted: () {}, // <- here
                  );
                });
          }
    
          Widget submitButton(Bloc bloc) {
            return StreamBuilder(
              stream: bloc.submitValid,
              builder: (context, snapshot) {
                return RaisedButton(
                  child: Text('Login'),
                  color: Colors.blue,
                  onPressed: snapshot.hasData ? bloc.submit : null,
                );
              },
            );
          }
        }
    
    
  • user12208004
    user12208004 about 4 years
    Thanks. I understand this way, but is there any other way? Maybe nesting is not as bad as I thought
  • Viren V Varasadiya
    Viren V Varasadiya about 4 years
    it is not possible in any other way because you have to call onSubmitted only so you have to follow this way only.
  • user12208004
    user12208004 about 4 years
    I got it. Thanks for your help!
  • Viren V Varasadiya
    Viren V Varasadiya about 4 years
    Accept the answer if you found it useful, so other also can get benefit. @user12208004