0

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

KJEjava48
  • 1,967
  • 7
  • 40
  • 69
  • https://stackoverflow.com/questions/69872798/dropdownbuttonformfield-reset-value-to-initial – Ayoub EL ABOUSSI Feb 09 '23 at 11:03
  • @AyoubELABOUSSI I don't want to reset the value. My problem is the dropdown automatically gets reset to default value on screen rotation. – KJEjava48 Feb 09 '23 at 11:07
  • You might get better answers if you provide a minimal piece of code where the problem can be reproduced. – deczaloth Feb 14 '23 at 08:27
  • @deczaloth Ok I edited my question with minimal code – KJEjava48 Feb 14 '23 at 11:46
  • Thanks! But still there are classes like `FinancialYear` wich i do not have access to. That means i can not build your code on my side to better try to find a solution for you. Could you create a minimal/self contained proyect where the problem you are facing is reflected? – deczaloth Feb 14 '23 at 11:51
  • setFinancialPeriodDropDown() method – KJEjava48 Feb 14 '23 at 11:53
  • when the screen orientation changes the financial year selected on dropdown gets reset to the initial value on dropdown. – KJEjava48 Feb 14 '23 at 11:54
  • FinancialYear just a model class with id,start date,end date fields. – KJEjava48 Feb 14 '23 at 11:55

1 Answers1

3

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.

Alex Sunder Singh
  • 2,378
  • 1
  • 7
  • 17
  • So ur telling that dropdown will work only with Stateful widget??.When i implemented the same dropdown inside a Dialog box in the same stateless widget, its working fine with orientation,then it should not work as per ur suggestion. – KJEjava48 Feb 14 '23 at 05:39
  • Ur answer may work but i have more modules in this widget that i didn't shared on the question,so its not easy or viable to convert it to a stateful widget?? – KJEjava48 Feb 14 '23 at 05:50
  • You should not have variable in `StatelessWidget`, you may use other state management system like `Bloc` or `GetXController` to manage it – Alex Sunder Singh Feb 14 '23 at 06:46
  • I was using Bloc for state management here – KJEjava48 Feb 14 '23 at 11:33
  • Then manage `FinancialYear selFinancialPeriod = FinancialYear(); dynamic selFinancialValue; List? financialYearList;` in `State` or `Bloc` – Alex Sunder Singh Feb 14 '23 at 11:35