Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to update the UI when items inside DropDownButtonFormField changes?

I was working with DropDownButtonFormField2 where the items come from the API call.

The problem is, when the API call is finished, the dropdown list items are not updated.
After the API call is finished, I already called setState(). But the item list is not updated, I need to go to other screen and go back to refresh the dropdown.
I am using mobx btw.

Any help would be appreciated. Thank you

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

my_screen.dart


class MyScreenState extends State<MyScreen> {

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async => false,
      child: Scaffold(
        key: _scaffoldKey,
        body: _buildItemDropDown(),
      ),
    );
  }

  @override
  void initState() {
    super.initState();
    _my_store.getItemList().then((value) {
      setState(() {});
    });
  }


_buildItemDropDown() {
    return DropdownButtonHideUnderline(
        key: UniqueKey(),
        child: DropdownButtonFormField2(
      decoration: InputDecoration(
        isDense: true,
        contentPadding: EdgeInsets.zero,
        border: OutlineInputBorder(
          borderRadius: BorderRadius.circular(4),
        ),
        focusedBorder: OutlineInputBorder(
            borderSide: BorderSide(color: ColorPalette.green[400]!)),
        enabledBorder: OutlineInputBorder(
            borderSide: BorderSide(color: ColorPalette.black[200]!)),
      ),
      isExpanded: true,
      hint: const Text(
        'Options',
        style: TextStyle(fontSize: 14),
      ),
      iconOnClick: SvgPicture.asset(
        'assets/svg/arrow_drop_down_activated.svg',
      ),
      icon: SvgPicture.asset(
        'assets/svg/arrow_drop_down.svg',
      ),
      iconSize: 30,
      isDense: true,
      buttonHeight: 40,
      buttonPadding: const EdgeInsets.only(left: 12, right: 12),
      dropdownDecoration: BoxDecoration(
        borderRadius: BorderRadius.circular(4),
      ),
      items: obsItemSpec.asMap().entries.map((item) {
        return DropdownMenuItem<String>(
          value: item.value,
          enabled: false,
          child: StatefulBuilder(
            builder: (context, menuSetState) {
              final _isSelected = selectedItems.contains(item.value);
              return InkWell(
                onTap: () {
                  _isSelected
                      ? selectedItems.remove(item.value)
                      : selectedItems.add(item.value);
                  setState(() {});
                  menuSetState(() {});
                },
                child: Container(
                  color: (item.key % 2 != 0)
                      ? ColorPalette.white[400]
                      : ColorPalette.white[500],
                  height: double.infinity,
                  padding:
                      const EdgeInsets.symmetric(horizontal: 18.0, vertical: 0),
                  child: Row(
                    children: [
                      _isSelected
                          ? SvgPicture.asset(
                              'assets/svg/checkbox_green_outlined.svg',
                            )
                          : SvgPicture.asset(
                              'assets/svg/checkbox_outlined_blank.svg',
                            ),
                      const SizedBox(width: 10),
                      Text(
                        item.value,
                        style: const TextStyle(
                          fontSize: 14,
                        ),
                      ),
                    ],
                  ),
                ),
              );
            },
          ),
        );
      }).toList(),
      itemPadding: EdgeInsets.zero,
      value: selectedItems.isEmpty ? null : selectedItems.last,
      validator: (value) {
        if (value == null) {
          return 'Please select gender.';
        }
      },
      onChanged: (value) {},
      selectedItemBuilder: (context) {
        return obsItemSpec.map(
          (item) {
            return Container(
              padding: const EdgeInsets.symmetric(horizontal: 0.0),
              child: Text(
                selectedItems.join(', '),
                style: const TextStyle(
                  fontSize: 14,
                  overflow: TextOverflow.ellipsis,
                ),
                maxLines: 1,
              ),
            );
          },
        ).toList();
      },
    ));
  }

my_store.dart

part 'my_store.g.dart';

class MyStore = _MyStore with _$MyStore;

abstract class _MyStore with Store {

@observable
Observable<List<ItemSpec>?> obsItemSpec = Observable<List<ItemSpec>?>(null);


@action
Future getItemList() async {
 final future = _useCase.getItemList();
    future.then((itemList) {
      obsItemSpec = Observable(itemList.map((list) =>
          ItemSpec(list.name, list.id)).toList());
    });
  }

enter image description here

>Solution :

I think that your then method inside of initState executes before your future.then is done inside of getItemList method because you are not awaiting your future inside it nor returning it. So I suggest something like this:

@action
Future getItemList() async {
  final itemList = await _useCase.getItemList();
  obsItemSpec = Observable(
      itemList.map((list) => ItemSpec(list.name, list.id)).toList());
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading