ERROR: The argument type 'Object?' can't be assigned to the parameter type 'String?'

Issue

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);
      }
    }
  );
}

Solution

You need to use

snapshot.error?.toString()

Answered By – Tolga Kartal

Answer Checked By – Gilberto Lyons (FlutterFixes Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *