flutterdartsetstatedropdownbox

DropdownButton doesn't change value and unable to be reused


I created a method for Dropdown button to reuse the code. Whenever the method is called, the button does not update. But the value updates in the console updates when I tried to debug. Even though I created the method in Stateful widget, setState method doesn't seem to work!

Here's the code and a couple of screenshots

class _SGPAState extends State<SGPA> {
  List<String> _credits = ['0', '1', '2', '3', '4', '5'];
  List<String> _grades = ['O', 'A+', 'A', 'B+', 'B', 'C', 'P', 'F', 'Ab', 'I'];

  List<String?> selectedCredit = List.filled(15, '0');
  List<String?> selectedGrade = List.filled(15, 'O');

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        SizedBox(
          height: 15,
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            Text('SNo', style: kGPATextStyle),
            Text('Credits', style: kGPATextStyle),
            Text('Grade', style: kGPATextStyle),
          ],
        ),
        SizedBox(
          height: 15,
        ),
        dataRow(index: 0),
        dataRow(index: 1),
        dataRow(index: 2),
        dataRow(index: 3),
        dataRow(index: 4),
      ],
    );
  }



  Row dataRow({required int index}) {
    return Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: [
          Text(
            '${index+1}',
            style: kGPATextStyle,
          ),
          buildDropdown(selectedValue: selectedCredit[index], selectedList: _credits),
          buildDropdown(selectedValue: selectedGrade[index], selectedList: _grades),
        ],
      );
  }

  DropdownButton<String> buildDropdown(
      {required String? selectedValue, required List<String> selectedList}) {
    return DropdownButton(
      value: selectedValue,
      items: selectedList.map((location) {
        return DropdownMenuItem(
          value: location,
          child: Text(
            location,
            style: kDropdownTextStyle,
          ),
        );
      }).toList(),
      onChanged: (String? newValue) {
        selectedValue = newValue;
        setState(() {
          selectedValue = newValue;
        });
        print(selectedValue);
      },
    );
  }
}

Dropdown buttons screenshot Console screenshot

I'm stuck with this for quite some time.

Can anyone tell me the reason for this issue? Or is there a solution?


Solution

  • You are assigning to the local variable selectedValue, which isn't persisted from one build to another. So if you want the value to be saved across builds, you have to assign it to an attribute on the state class (like selectedCredit/selectedGrade).

    Here's a possible solution to your problem:

    Row dataRow({required int index}) {
      return Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: [
          Text(
            '${index + 1}',
            style: kGPATextStyle,
          ),
          buildDropdown(
            selectedValue: selectedCredit[index],
            onSelected: (v) => setState(() {
              selectedCredit[index] = v;
            }),
            selectedList: _credits,
          ),
          buildDropdown(
            selectedValue: selectedGrade[index],
            onSelected: (v) => setState(() {
              selectedGrade[index] = v;
            }),
            selectedList: _grades,
          ),
        ],
      );
    }
    
    DropdownButton<String> buildDropdown({
      required final String? selectedValue,
      required final ValueSetter<String?> onSelected,
      required final List<String> selectedList,
    }) {
      return DropdownButton(
        value: selectedValue,
        items: selectedList.map((location) {
          return DropdownMenuItem(
            value: location,
            child: Text(
              location,
              style: kDropdownTextStyle,
            ),
          );
        }).toList(),
        onChanged: (String? newValue) {
          onSelected(newValue);
        },
      );
    }