Flutter : DropdownButtonFormField2 selected item changes to initial value on screen rotation

1.1k Views Asked by At

In my flutter application screen I have a DropdownButtonFormField2 which list various financial years, where after fetching the financial year list I set the current financial year as the initial(default) selected value in the dropdown as code below.The Problem comes when I change the financial year to a different year in dropdown, and it will change to the newly selected financial year in dropdown, but it will reset to the current(initial/default) financial year when I rotate the screen. How to solve this issue?

class AccountSetup extends StatelessWidget {
    FinancialYear selFinancialPeriod = FinancialYear();
    dynamic selFinancialValue;
    List<dynamic>? financialYearList;
    final Company selectedCompany;

    AccountSetup({Key? key, required this.selectedCompany}) : super(key: key);


    @override
    Widget build(BuildContext context) {
        context.read<MyAccountBloc>().add(FetchFinancialYearList(selectedCompany.id!));
        return BlocBuilder<MyAccountBloc, MyAccountState>(
            builder: (context, state) {
            if(state is FinancialYearList) {
                financialYearList = state.list;
                if(financialYearList != null) {
                    for(dynamic itemFY in financialYearList!) {
                        if(DateTime.now().isBetween(yMdFormat.parse(itemFY['startDate']), yMdFormat.parse(itemFY['endDate']))) {
                            selFinancialPeriod = FinancialYear.fromJson(itemFY);
                            selFinancialValue = itemFY;
                            break;
                        }
                    }
                }
                getFinancialPeriodDropDown(context);
            } else if(state is AccountTabChanged) {
                ....
            } else if(state is UpdateDropDown) {
                selFinancialValue = state.selValue;
                selFinancialPeriod = FinancialYear.fromJson(selFinancialValue);
                getFinancialPeriodDropDown(context);
            }
            return MaterialApp(
                home: Scaffold(
                body: SafeArea(
                    child: Stack(
                        children: [
                            Container(
                                child: Column(
                                    children: [
                                        SizedBox(height: 3,),
                                        getFinancialPeriodDropDown(context),
                                        SizedBox(height: 3,),
                                        DefaultTabController(
                                            length: 2, // length of tabs
                                            initialIndex: 0,
                                            child: Builder(
                                                builder: (context) {
                                                    tabController = DefaultTabController.of(context);
                                                    tabController?.addListener(() {
                                                        selTab = tabController?.index;
                                                        context.read<MyAccountBloc>().add(ChangeTabEvent(tabIndex: tabController?.index));
                                                    });
                                                    return Column(
                                                        children: <Widget>[
                                                            ....
                                                        ],
                                                    );
                                                },
                                            ),
                                        ),
                                    ],
                                ),
                            ),
                            Positioned(
                                bottom: 0,
                                left: 30,
                                right: 30,
                                child: getTabButtons(context),
                            ),
                        ],
                    )
                ),
                ),
            );
            }
        );
    }

    getFinancialPeriodDropDown(BuildContext context) {
        if(financialYearList == null) {
            return SizedBox();
        }
        return setAcademicDropDown(context);
    }

    setFinancialPeriodDropDown(BuildContext context) {
        return SizedBox(
            height: 45,
            child: DropdownButtonFormField2<dynamic>(
                isExpanded: true,
                hint: const Text('Select Financial Year',style: TextStyle(fontSize: 14),),
                value: selFinancialValue,
                items: financialYearList!.map((item) => DropdownMenuItem<dynamic>(
                    value: item,
                    child: Text('${dMyFormat.format(yMdFormat.parse(item['startDate']))} :: ${dMyFormat.format(yMdFormat.parse(item['endDate']))}',
                        style: const TextStyle(fontSize: 14,),
                    ),)).toList(),
                validator: (value) {
                    if (value == null) {
                        return 'Please select $txtAcaPer.';
                    }
                },
                onChanged: (value) {
                    context.read<MyAccountBloc>().add(UpdateDropDownEvent(selValue: value));
                },
                onSaved: (value) {},
            ),
        );
    }

}

One more thing I need to know is, how can i set the initial(default) value to nothing (ie, like 'Select Financial Year') when I open the page instead of the current financial year??

Edit :

I saw same kind of problem on the below question also

flutter dropdownbutton won't keep answer after scrolling

1

There are 1 best solutions below

5
Alex Sunder Singh On BEST ANSWER

If you really don't want to lose the selection on orientation change then make the AccountSetup widget as StatefulWidget.

Then your code will be as following

class AccountSetup extends StatefulWidget {
  final Company selectedCompany;

  AccountSetup({Key? key, required this.selectedCompany}) : super(key: key);

  @override
  State<AccountSetup> createState() => _AccountSetupState();
}

class _AccountSetupState extends State<AccountSetup> {
  FinancialYear selFinancialPeriod = FinancialYear();
  dynamic selFinancialValue;
  List<dynamic>? financialYearList;

  @override
  Widget build(BuildContext context) {
    context.read<MyAccountBloc>().add(FetchFinancialYearList(widget.selectedCompany.id!));
    return BlocBuilder<MyAccountBloc, MyAccountState>(
        builder: (context, state) {
          if(state is FinancialYearList) {
            financialYearList = state.list;
            if(financialYearList != null) {
              for(dynamic itemFY in financialYearList!) {
                if(DateTime.now().isBetween(yMdFormat.parse(itemFY['startDate']), yMdFormat.parse(itemFY['endDate']))) {
                  selFinancialPeriod = FinancialYear.fromJson(itemFY);
                  selFinancialValue = itemFY;
                  break;
                }
              }
            }
            getFinancialPeriodDropDown(context);
          } else if(state is AccountTabChanged) {
            selTab = state.tabIndex;
            //tabController!.index = selTab!;
            getTabButtons(context);
          } else if(state is UpdateDropDown) {
            selFinancialValue = state.selValue;
            selFinancialPeriod = FinancialYear.fromJson(selFinancialValue);
            getFinancialPeriodDropDown(context);
          }
          return MaterialApp(
            scrollBehavior: MyCustomScrollBehavior(),
            title: ....,
            debugShowCheckedModeBanner: false,
            theme: ThemeData(
              colorScheme: ColorScheme.fromSwatch().copyWith(
                primary: primaryColor,
              ),),
            home: Scaffold(
              resizeToAvoidBottomInset: false,
              appBar: sizedAppBar,
              body: SafeArea(
                  child: Stack(
                    children: [
                      Container(
                        child: Column(
                          children: [
                            SizedBox(height: 3,),
                            getFinancialPeriodDropDown(context),
                            SizedBox(height: 3,),
                            DefaultTabController(
                              length: 2, // length of tabs
                              initialIndex: 0,
                              child: Builder(
                                builder: (context) {
                                  tabController = DefaultTabController.of(context);
                                  tabController?.addListener(() {
                                    selTab = tabController?.index;
                                    context.read<MyAccountBloc>().add(ChangeTabEvent(tabIndex: tabController?.index));
                                  });
                                  return Column(
                                    children: <Widget>[
                                      Container(
                                        child: TabBar(
                                          controller: tabController,
                                          labelColor: textWhite1,
                                          unselectedLabelColor: Colors.black,
                                          indicatorWeight: 2,
                                          isScrollable: true,
                                          indicatorSize: TabBarIndicatorSize.tab,
                                          indicatorColor: selColor1,
                                          indicatorPadding: EdgeInsets.only(left: 2.0, right: 2.0,bottom: 3.0),
                                          indicator: BoxDecoration(
                                            borderRadius: BorderRadius.circular(5),color: highlightGrey10,shape: BoxShape.rectangle,
                                          ),
                                          labelPadding: EdgeInsets.symmetric (horizontal: 1),
                                          tabs: [
                                            Container(
                                              width: mainTabWidth,
                                              height: mainTabHeight,
                                              decoration: BoxDecoration(color: tab1Color,border: Border.all(color: border1Color,width: 2,style: BorderStyle.solid),borderRadius: BorderRadius.circular(5)),
                                              child: Tab(child:Text(tabAccSt1,textAlign: TextAlign.center,style: TextStyle(fontSize: fontSize,fontWeight: FontWeight.bold,),),),
                                            ),
                                            Container(
                                              width: mainTabWidth,
                                              height: mainTabHeight,
                                              decoration: BoxDecoration(color: tab2Color,border: Border.all(color: border1Color,width: 2,style: BorderStyle.solid),borderRadius: BorderRadius.circular(5)),
                                              child: Tab(child:Text(tabAccSt2,textAlign: TextAlign.center,style: TextStyle(fontSize: fontSize,fontWeight: FontWeight.bold,),),),
                                            ),
                                          ],
                                        ),
                                      ),
                                      Container(
                                        height: 400, //height of TabBarView
                                        decoration: BoxDecoration(
                                            border: Border(top: BorderSide(color: Colors.grey, width: 0.5))
                                        ),
                                        child: TabBarView(
                                          controller: tabController,
                                          children: <Widget>[
                                            Container(
                                              child: Column(
                                                children: [
                                                  getCompanySites(),
                                                ],
                                              ),
                                            ),
                                            Container(
                                              child: Center(
                                                child: Text('Display Tab 2', style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold)),
                                              ),
                                            ),
                                          ],
                                        ),
                                      ),
                                    ],
                                  );
                                },
                              ),
                            ),
                          ],
                        ),
                      ),
                      Positioned(
                        bottom: 0,
                        left: 30,
                        right: 30,
                        child: getTabButtons(context),
                      ),
                    ],
                  )
              ),
            ),
          );
        }
    );
  }

  getFinancialPeriodDropDown(BuildContext context) {
    if(financialYearList == null) {
      return SizedBox();
    }
    return setAcademicDropDown(context);
  }

  setFinancialPeriodDropDown(BuildContext context) {
    return SizedBox(
      height: 45,
      child: DropdownButtonFormField2<dynamic>(
        isExpanded: true,
        hint: const Text('Select Financial Year',style: TextStyle(fontSize: 14),),
        value: selFinancialValue,
        icon: const Icon(Icons.arrow_drop_down,color: Colors.black45,),
        iconSize: 30,
        buttonHeight: 60,
        buttonPadding: const EdgeInsets.only(left: 20, right: 10),
        dropdownDecoration: BoxDecoration(borderRadius: BorderRadius.circular(15),),
        items: financialYearList!.map((item) => DropdownMenuItem<dynamic>(
          value: item,
          child: Text('${dMyFormat.format(yMdFormat.parse(item['startDate']))} :: ${dMyFormat.format(yMdFormat.parse(item['endDate']))}',
            style: const TextStyle(fontSize: 14,),
          ),)).toList(),
        validator: (value) {
          if (value == null) {
            return 'Please select $txtAcaPer.';
          }
        },
        onChanged: (value) {
          context.read<MyAccountBloc>().add(UpdateDropDownEvent(selValue: value));
        },
        onSaved: (value) {},
      ),
    );
  }
}

If you not seeing any changes on UI then, you have to call setState method to refresh the UI.