Search code examples
flutter

Bloc login example - how does this form actually work?


Trying to learn BLoC, and running through some of the examples.

I'm looking at the login example. But no matter how long I stare at it, I cannot figure out a particular thing that I'm not sure is related to BLoC at all.

How does the submit button move back and forth between enabled and disabled depending on the form inputs? They use a library "Formz" but I still cannot figure out what magic may be happening to connect the two text inputs to the state of the button.

I basically just want to know why the button is only clickable when the two text inputs are filled out. There is no obvious code that does this or any form config, etc.

Code: https://github.com/felangel/bloc/tree/master/examples/flutter_login/


Solution

  • You can use like this. Event Class :

      class InputChangedEvent extends InputEvent {
      final String inputText1;
      final String inputText2;
    
      InputChangedEvent(this.inputText1, this.inputText2);
    }
    

    State class :

    abstract class InputState {}
    
    class InputInitialState extends InputState {}
    
    class InputValidState extends InputState {}
    
    class InputInvalidState extends InputState {}
    

    Bloc class :

    class InputBloc extends Bloc<InputEvent, InputState> {
      InputBloc() : super(InputInitialState());
    
      @override
      Stream<InputState> mapEventToState(InputEvent event) async* {
        // In older versions, we used mapEventToState, now you use emit directly inside the event handler.
    
        if (event is InputChangedEvent) {
          // You can simply use `emit` inside the handler now.
          if (event.inputText.isEmpty) {
            emit(InputInvalidState()); // Emit an invalid state if the input is empty
          } else {
            emit(InputValidState()); // Emit a valid state if the input is not empty
          }
        }
      }
    }
    

    UI side :

    class MyFormPage extends StatelessWidget {
      final TextEditingController _controller1 = TextEditingController();
      final TextEditingController _controller2 = TextEditingController();
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('Enable/Disable Button')),
          body: BlocProvider(
            create: (context) => InputBloc(),
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: Column(
                children: [
                  // First input field
                  TextField(
                    controller: _controller1,
                    decoration: InputDecoration(labelText: 'Enter First Text'),
                    onChanged: (input) {
                      // Trigger event whenever the first input changes
                      context.read<InputBloc>().add(InputChangedEvent(
                          input, _controller2.text)); // Pass both field values
                    },
                  ),
                  SizedBox(height: 20),
                  // Second input field
                  TextField(
                    controller: _controller2,
                    decoration: InputDecoration(labelText: 'Enter Second Text'),
                    onChanged: (input) {
                      // Trigger event whenever the second input changes
                      context.read<InputBloc>().add(InputChangedEvent(
                          _controller1.text, input)); // Pass both field values
                    },
                  ),
                  SizedBox(height: 20),
                  // Button
                  BlocBuilder<InputBloc, InputState>(
                    builder: (context, state) {
                      return ElevatedButton(
                        onPressed: state is InputValidState
                            ? () {
                                // Handle button press
                                ScaffoldMessenger.of(context).showSnackBar(
                                  SnackBar(content: Text('Button Pressed')),
                                );
                              }
                            : null, // Button is disabled when InputInvalidState
                        child: Text('Submit'),
                      );
                    },
                  ),
                ],
              ),
            ),
          ),
        );
      }
    }