skip to Main Content

When using a DropdownButtonFormField instead of a DropdownButton, the selectedValue given is not taken into account when rebuilding the widget. When can I do to circumvent this ?

import 'package:flutter/material.dart';


void main() {
  runApp(
    MaterialApp(
      home: HomeRoute(),
    ),
  );
}

class HomeRoute extends StatefulWidget {
  const HomeRoute({super.key});

  @override
  State<HomeRoute> createState() => _HomeRouteState();
}

class _HomeRouteState extends State<HomeRoute> {
  String selectedValue = '1';

  @override
  Widget build(BuildContext context) {
    print('Building with selected value : $selectedValue');
    return Scaffold(
      appBar: AppBar(title: const Text('Title'),),
      body: Column(
        children: [
          DropdownButtonFormField<String>(
            value: selectedValue,
            onChanged: (value) {
              setState(() {
                // Not updating the value
                // selectedValue = value!;
              });
            },
            items: [
              for(int i = 0; i < 10; i++)
                DropdownMenuItem<String>(value: '$i', child: Text('$i'),),
            ],
          ),
        ],
      ),
    );
  }
}

Stackoverflow tells me that I need to add more details, but there’s nothing more to be said.

2

Answers


  1. Chosen as BEST ANSWER

    Found a workaround to force the DropdownButtonFormField to update its internal index value by calling didUpdateWidget :

    import 'package:flutter/material.dart';
    
    
    void main() {
      runApp(
        MaterialApp(
          home: HomeRoute(),
        ),
      );
    }
    
    class HomeRoute extends StatefulWidget {
      const HomeRoute({super.key});
    
      @override
      State<HomeRoute> createState() => _HomeRouteState();
    }
    
    class _HomeRouteState extends State<HomeRoute> {
      String selectedValue = '1';
      GlobalKey<State> dropdownButtonFormFieldKey = GlobalKey();
    
      @override
      Widget build(BuildContext context) {
        print('Building with selected value : $selectedValue');
        return Scaffold(
          appBar: AppBar(title: const Text('Title'),),
          body: Column(
            children: [
              DropdownButtonFormField<String>(
                key: dropdownButtonFormFieldKey,
                value: selectedValue,
                onChanged: (value) async {
                  setState(() {
                    // Not updating the value
                    // selectedValue = value!;
                  });
                  dropdownButtonFormFieldKey.currentState?.didUpdateWidget(DropdownButtonFormField<String>(items: [], onChanged: (_) {},));
                  dropdownButtonFormFieldKey.currentState?.setState(() {});
                },
                items: [
                  for(int i = 0; i < 10; i++)
                    DropdownMenuItem<String>(value: '$i', child: Text('$i'),),
                ],
              ),
            ],
          ),
        );
      }
    }
    

    Of course this makes the code quite horrendous to look at, but it works and seemingly without side-effects as didUpdateWidget doesn't do much other then update the index.


  2. Try below code hope its help to you Using DropdownButton

    DropdownButton<String>(
            value: selectedValue,
            onChanged: (value) {
              setState(() {
                selectedValue = value!;
              });
            },
            items: [
              for (int i = 0; i < 10; i++)
                DropdownMenuItem<String>(
                  value: '$i',
                  child: Text('$i'),
                ),
            ],
          ),
    

    Using DropdownButtonFormField

    DropdownButtonFormField<String>(
                  value: selectedValue,
                  onChanged: (value) {
    //               setState(() {
    //                 selectedValue = value!;
    //               });
                  },
                  items: [
                    for (int i = 0; i < 10; i++)
                      DropdownMenuItem<String>(
                        value: '$i',
                        child: Text('$i'),
                      ),
                  ],
                ),
    

    Result before selection: image

    Result after selection: image

    DropdownButton: It doesn’t maintain any state related to the selected value. If you want to update the selected value of a DropdownButton, you need to manage the state, using a StatefulWidget or a state management.

    DropdownButtonFormField: This means it automatically manages the state of the selected value. When you select an item from the dropdown, the form field value is automatically updated.

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