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,
);
});
});
}
Author by
user12208004
Updated on December 18, 2022Comments
-
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 about 4 yearsThanks. I understand this way, but is there any other way? Maybe nesting is not as bad as I thought
-
Viren V Varasadiya about 4 yearsit is not possible in any other way because you have to call onSubmitted only so you have to follow this way only.
-
user12208004 about 4 yearsI got it. Thanks for your help!
-
Viren V Varasadiya about 4 yearsAccept the answer if you found it useful, so other also can get benefit. @user12208004