Flutter DropDownMenu Button update an existing record

I have been experimenting with my flutter drop down button. Context of what I am doing. I have an app that will create a job and give it to an available staff member. I have stored all my staff members in a list for the menu button. I will put the code below to show the creation of the job ticket drop down button. selectedTech is at the top of the program so that's not the issue

String selectedTech = "";
Container(
                      // margin: EdgeInsets.only(right: 20),
                      width: MediaQuery.of(context).size.width / 2.5,
                      child: DropdownButton(
                        hint: Text(
                          selectedTech,
                          style: TextStyle(color: Colors.blue),
                        ),
                        isExpanded: true,
                        iconSize: 30.0,
                        style: TextStyle(color: Colors.blue),
                        items: listStaffUsers.map(
                          (val) {
                            return DropdownMenuItem<String>(
                              value: val,
                              child: Text(val),
                            );
                          },
                        ).toList(),
                        onChanged: (val) {
                          setState(
                            () {
                              selectedTech = val.toString();
                            },
                          );
                        },
                      ),
                    ),

The above code works perfect. However when I want to update the job ticket to change the available staff member I want to set the initial value of the drop down menu to the staff member assigned to the job, because it isn't always guaranteed that they change the staff member allocated to the job. When I set the selected value to my initial value I am locked with that value and cannot change it. Here is the code I am using to update the staff member.

  String selectedTech = "";
int the build method I add
selectedTech = widget.staff;
Container(
                      // margin: EdgeInsets.only(right: 20),
                      width: MediaQuery.of(context).size.width / 2.5,
                      child: DropdownButton(
                        hint: Text(
                          selectedTech,
                          style: TextStyle(color: Colors.blue),
                        ),
                        isExpanded: true,
                        iconSize: 30.0,
                        style: TextStyle(color: Colors.blue),
                        items: listStaffUsers.map(
                          (val) {
                            return DropdownMenuItem<String>(
                              value: val,
                              child: Text(val),
                            );
                          },
                        ).toList(),
                        onChanged: (val) {
                          setState(
                            () {
                              selectedTech = val.toString();
                            },
                          );
                        },
                      ),
                    ),

Any Guidance or examples will be greatly appreciated.


Solution 1:

As I understand under the Widget build method you set selectedTech = widget.staff and then return the widget like this:

Widget build(BuildContext context) {
    selectedTech = widget.staff;
    return Container( ...

This will systematically lock your selectedTech to widget.staff whenever the build method is called (when you call setState). I mean whenever you change the value of the dropdown, the value will not be set the actual value on the dropdown menu. Because you call setState, setState builds the widget from scratch and selectedTech = widget.staff is called in these steps.

Instead of in build method you should initialize it first, then continue to build method.

class _StaffHomeState extends State<StaffHome> {
   String? selectedTech;
   // Write a function to initialize the value of selectedTech
   void initializeSelectedTech () {
    selectedTech = widget.staff;
   }


   // Call this function in initState to initialize the value
   @override
   void initState() {
       initializeSelectedTech();
       super.initState();
   }


   // Then Widget build method
   Widget build(BuildContext context) {
       return Container( .....

By this way, you initialize first the value before build method and whenever state changes, the data will be persisted. I hope it is helpful.