I have a TextFormField widget wrapped inside a StreamBuilder, in TextFormField widget, inside the decoration, when is pass snapshot.error to the errorText argument, it gives an error:
The argument type 'Object?' can't be assigned to the parameter type 'String?'
Here is the code for state class with form and TextFormField
class LoginScreen extends StatefulWidget{
State<StatefulWidget> createState() {
return _LoginScreen();
}
}
class _LoginScreen extends State<LoginScreen>{
final form_key = GlobalKey<FormState>();
Widget build(context){
return Container(
margin: EdgeInsets.all(20),
child: Form(
key: form_key,
child: Column(
children: [
emailField(),
passwordField(),
Padding(
padding: EdgeInsets.all(7),
child: submitButton(),
),
Padding(
padding: EdgeInsets.all(7),
child: ResetButton(),
)
],
),
),
);
}
Widget emailField(){
return StreamBuilder(
stream: bloc.email,
builder: (context, snapshot){
return TextFormField(
decoration: const InputDecoration(
labelText: 'Email',
errorText: snapshot.error,
),
keyboardType: TextInputType.emailAddress,
onChanged: bloc.changeEmail,
);
},
);
}
Widget passwordField(){
return StreamBuilder(
stream: bloc.pass,
builder: (context, snapshot){
return TextFormField(
decoration: const InputDecoration(
labelText: 'Password'
errorText: snapshot.error,
),
obscureText: true,
);
},
);
}
Widget submitButton(){
return ElevatedButton(
child: Text('SUBMIT'),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.resolveWith(getColor),
),
onPressed: (){},
);
}
Widget ResetButton(){
return ElevatedButton(
child: Text('RESET'),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.resolveWith(getColor),
),
onPressed: (){
form_key.currentState!.reset();
}
);
}
Color getColor(Set<MaterialState> states) {
const Set<MaterialState> interactiveStates = <MaterialState>{
MaterialState.pressed,
MaterialState.hovered,
MaterialState.focused,
};
if (states.any(interactiveStates.contains)) {
return Colors.orange.shade600;
}
return Colors.blue.shade400;
}
}
The code of my bloc class:
class Bloc with Validators{
final _email = StreamController<String?>();
final _pass = StreamController<String?>();
//get access to stream
Stream<String?> get email => _email.stream.transform(validate_email);
Stream<String?> get pass => _pass.stream.transform(validate_password);
//change new data
Function(String?) get changeEmail => _email.sink.add;
Function(String?) get changePass => _pass.sink.add;
dispose(){
_email.close();
_pass.close();
}
}
And here is validator class:
class Validators{
final validate_email = StreamTransformer<String?, String?>.fromHandlers(
handleData: (String? email, sink){
if(email!.contains('@')){
sink.add(email);
}else{
sink.addError('Enter valid email');
}
}
);
final validate_password = StreamTransformer<String?, String?>.fromHandlers(
handleData: (String? pass, sink){
if(pass!.length < 4){
sink.addError('Enter valid password');
}else{
sink.add(pass);
}
}
);
}
You need to use
snapshot.error?.toString()