skip to Main Content

I have two drop downs, and I want to do things when they get values selected. One of those is to change the second buttondrop items based on what’s selected in the first dropdown.
For example:

Dropdown1 is a list of car manufactuers

Dropdown2 is a list of their models

Dropdown1 selects mercedes

Dropdown2 gets "E Class, S Class" etc

Dropdown1 selects lexus

Dropdown2 gets "ES, LS", etc

(Eventually the second drop down will update a listview as well, but haven’t gotten to that yet.)

Data wise, it works, I update the list. The problem is the UI won’t update unless I do a hot reload

Currently I am just having the dropdowns fetch their data and using Future builders

Future? data1;
Future? data2;

void initState(){
   super.initState();
   data1 = _data1AsyncMethod();
   data2 = _data2AsyncMethod();
}

_data2AsyncMethod([int? item1_id]) async{
   if(item1_id == null){
     item2Classes = await DefaultItems().getAllItem2Classes();
     listOfItem2ClassNames = DefaultItems().returnListOfItemClassNames(item2Classes);
   }
   else{
     // The methods below calls the DefaultItems methods which have Futures all in them.
     // The getAllItems calls a network file with GET methods of future type to get data and decodes them, etc. 
    // They build a list of the object type, ex List<Item2>

     item2Classes = await DefaultItems().getAllItem2Classes(item1_id);
     listOfItem2ClassNames = DefaultItems().returnListOfItemClassNames(item2Classes);
   }
}

I have this Future Builder nested in some containers and paddings

FutureBuilder{
   future: data2,
   builder: (context, snapshot){
      if(snapshot.connectionState != done...)
         // return a circle progress indictator here
      else{
         return CustomDropDown{
               hintText: 'example hint'
               dropDownType: 'name'
               dropDownList: listOfItem2ClassNames
               dropDownCallback: whichDropDown,
         }

The onChanged in CustomDropDown passes the dropDownType and the dropDownValue

The callback

whichDropDown(String dropDownType, String dropDownValue){
   if(dropDownType == 'item1'){
      //so if the first dropdown was used
     // some code to get item_1's id and I call the data2 method

     _data2AsyncMethod(item1_id);
}

Again the data updates (listOfItem2ClassNames) BUT the UI won’t update unless I hot reload. I’ve even called just setState without any inputs to refresh but doesn’t work

So how do I get the UI to update with the data, and is my solution too convoluted in the first place? How should I solve? StreamBuilders? I was having trouble using them.

Thanks

2

Answers


  1. If you do a setState in the whichDropDown function, it will rebuild the UI. Although I’m not exactly sure what you want, your question is really ambiguous.

    whichDropDown(String dropDownType, String dropDownValue){
       if(dropDownType == 'item1'){
          //so if the first dropdown was used
         // some code to get item_1's id and I call the data2 method
    
         _data2AsyncMethod(item1_id).then((_) {
           setState(() {});
         });
       }
    }
    
    Login or Signup to reply.
  2. I notice a couple things:

    1. nothing is causing the state to update, which is what causes a rebuild. Usually this is done explicitly with a call to setState()
    2. in whichDropdown(), you call _data2AsyncMethod(item1_id), but that is returning a new Future, not updating data2, which means your FutureBuilder has no reason to update. Future's only go from un-completed to completed once, so once the Future in the FutureBuilder has been completed, there’s no reason the widget will update again.

    You may want to think about redesigning this widget a bit, perhaps rather than relying on FutureBuilder, instead call setState to react to the completion of the Futures (which can be done repeatedly, as opposed to how FutureBuilder works)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search