sharmaji saheb
sharmaji saheb

Reputation: 57

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

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

Upvotes: 0

Views: 1183

Answers (3)

Lutfor Rahman
Lutfor Rahman

Reputation: 95

Interestingly no one knows the solution as they didn't face the problem.

You've to just remove the const keyword before InputDecoration(),

The below code will not work as it has the const keyword -

TextFormField(
    decoration: const InputDecoration(
                labelText: 'Email', errorText: snapshot.error),

    keyboardType: TextInputType.emailAddress,
         onChanged: bloc.changeEmail,
 );

But this piece of code will work as it does not have the const keyword -

TextFormField(
        decoration: InputDecoration(
                    labelText: 'Email', errorText: snapshot.error),
    
        keyboardType: TextInputType.emailAddress,
             onChanged: bloc.changeEmail,
     );

Upvotes: 1

Huthaifa Muayyad
Huthaifa Muayyad

Reputation: 12353

errorText: snapshot.hasError ? snapshot.error.toString() : "",

This will check if there is an error before converting it to a string. If there is no error, it'll prevent runtime null exceptions as well.

Upvotes: 2

Tolga Kartal
Tolga Kartal

Reputation: 633

You need to use

snapshot.error?.toString()

Upvotes: 2

Related Questions