skip to Main Content

I have a ConsumerWidget, which I’m using to watch the state of a provider. Anyways everything is working, besides my TextEditingControllers. Whenever I type something into the text field and click the done button on the phone keyboard, the textfields goes empty again. I think this is due to the state of that widget. So my question is how do I use the TextEditingController inside the ConsumerWidget, which has no createState method?

Here is my code. Thanks in advance:


class MainPage extends ConsumerWidget {
  const MainPage({super.key});

  @override
  Widget build(BuildContext context, ref) {
    // provider
    final roomListData = ref.watch(roomDataProvider);

    final roomService = RoomService();

    final roomIDController = TextEditingController();
    final roomPasswordController = TextEditingController();

    // UI screen size
    final size = MediaQuery.of(context).size;

    double deviceWidth = size.width;
    double deviceHeight = size.height;

    return Scaffold(
        backgroundColor: bluePrimary,
        body: SingleChildScrollView(
          child: roomListData.when(
              data: (data) {
                List<RoomModelResponse> roomList =
                    data.map((room) => room).toList();
                return SafeArea(
                    child: Container(
                  padding:
                      const EdgeInsets.symmetric(horizontal: 36, vertical: 16),
                  child: Column(
                      //crossAxisAlignment: CrossAxisAlignment.center,
                      children: [
                        Row(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            IconButton(
                              iconSize: deviceWidth * 0.09,
                              icon: const Icon(Icons.person_outline,
                                  color: orangePrimary),
                              onPressed: () {
                                Navigator.push(
                                    context,
                                    MaterialPageRoute(
                                        builder: (context) =>
                                            const DetailedProfilePage()));
                              },
                            ),
                            IconButton(
                              icon: const Icon(
                                Icons.add,
                                color: orangePrimary,
                              ),
                              iconSize: deviceWidth * 0.09,
                              onPressed: () {
                                Navigator.push(
                                  context,
                                  MaterialPageRoute(
                                      builder: (context) =>
                                          const CreateRoomScreen()),
                                );
                              },
                            )
                          ],
                        ),
                      
                        SizedBox(height: deviceHeight * 0.04),
                        Align(
                          alignment: Alignment.centerLeft,
                          child: Text("Join room",
                              style: TextStyle(
                                fontFamily: 'Chalet',
                                fontSize: deviceWidth * 0.05,
                                color: whitePrimary,
                                fontWeight: FontWeight.w100,
                              )),
                        ),
                        SizedBox(height: deviceHeight * 0.008),

                        // room ID textField
                        SizedBox(
                          width: MediaQuery.of(context).size.width * 0.85,
                          child: TextField(
                            controller: roomIDController,
                            decoration: InputDecoration(
                                filled: true,
                                fillColor: whitePrimary,
                                border: OutlineInputBorder(
                                    borderRadius: BorderRadius.circular(12),
                                    borderSide: BorderSide.none),
                                hintText: 'Enter room ID to join it',
                                hintStyle: const TextStyle(
                                    color: Color.fromARGB(255, 174, 173, 173))),
                          ),
                        ),

                        SizedBox(height: deviceHeight * 0.01),

                        // room password textField
                        SizedBox(
                          width: MediaQuery.of(context).size.width * 0.85,
                          child: TextField(
                            obscureText: true,
                            controller: roomPasswordController,
                            decoration: InputDecoration(
                                filled: true,
                                fillColor: whitePrimary,
                                border: OutlineInputBorder(
                                    borderRadius: BorderRadius.circular(12),
                                    borderSide: BorderSide.none),
                                hintText:
                                    'Leave blank if the room has no password',
                                hintStyle: const TextStyle(
                                    color: Color.fromARGB(255, 174, 173, 173))),
                          ),
                        ),

...

2

Answers


  1. You need to have StatefulWidget when working with TextEditingController since every time parameters of your widget change, it triggers build() method, which recreates your controllers, making them empty. Refer to this part of flutter guide.

    When working with recent versions of riverpod you need to use ConsumerStatefulWidget which is exactly like StatefulWidget syntactically, but with "Consumer" before every class name.

    Your resulting widget should create

    // probably some other vars too
    final roomIDController = TextEditingController();
    final roomPasswordController = TextEditingController();
    

    outside of the build() method, inside of _State class

    Login or Signup to reply.
  2. You can also use hooks (flutter_hooks package) and use HookConsumerWidget. Then your code will be even shorter. You will also need a package hooks_riverpod:

    class MainPage extends HookConsumerWidget {
      const MainPage({super.key});
    
      @override
      Widget build(BuildContext context, ref) {
    
        final roomListData = ref.watch(roomDataProvider);
    
        final roomIDController = useTextEditingController();
        final roomPasswordController = useTextEditingController();
    
        return Scaffold(...);
      }
    }
    

    Hooks take care of the lifecycle of objects themselves, so you don’t have to manually dispose of them via the dispose method.

    Links:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search