Flutter Prevent FutureBuilder from running twice - flutter

I am using FutureBuilder in flutter to fill up a drop down menu DropdownButtonFormField, i have the method
onChanged: (String? newValue) {
setState(() {
dropdownBrokers = newValue!;
});
},
Which allows the widget to rebuild and then assign the new value selected from the dropdown list. However, i am now experiencing a problem from my research stating that whenever the setState() is called, the future builder runs again, which makes my dropdown menu populate again. This is the full code snippet
FutureBuilder <List<Broker>>(
future: brokerData,
builder: (context, snapshot){
if(snapshot.hasData){
//do what needs to be done here
List<Broker>? data = snapshot.data;
for(var i = 0; i< data!.length; i++){
_brokers.add(data[i].firmName);
print(data[i].firmName);
}
return Container(
padding: EdgeInsets.all(10),
child: InputDecorator(
decoration: InputDecoration(
labelStyle: TextStyle(
color: Colors.grey
),
isDense: true,
contentPadding: EdgeInsets.all(7.0),
errorStyle: TextStyle(color: Colors.redAccent, fontSize: 16.0),
hintText: 'Select Broker',
border: OutlineInputBorder(borderRadius: BorderRadius.circular(5.0))),
child: DropdownButtonHideUnderline(
child: DropdownButtonFormField<String>(
alignment: Alignment.center,
value: dropdownBrokers,
icon: const Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: const TextStyle(color: Colors.indigo),
onChanged: (String? newValue) {
setState(() {
dropdownBrokers = newValue!;
});
},
items: _brokers.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
),
),
),
);
Also i get an error when i reselect an item.
How do i prevent the FutureBuilder from running twice

FutureBuilder will always be rendered once unless recreated in the build method. So the solution to this can be done in two ways:
1: Only calling brokerData in the FutureBuilder method or
2: Only calling brokerData in the initState override.
You can not do both.
And I assume the data to be populated in the dropdown comes from the future builder. Then use snapshot.data of the future instead of an already created value in this case:
items: _brokers.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
Change to:
items: snapshot.data.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);

Related

How to limit dropdown item list and make it scrollable

I'm new to flutter and currently I'm trying to create a reusable dropdown button. The problem now is I wanted to have 15 item in my dropdown item list and it's taking all my screen space. I wanted to limit them so at first it will only show around 5-6 item and the user can scroll down the dropdown List and show the rest of the item list.
How can I achieve this ?
Here's my current code for reusable dropdown Button:
Widget build(BuildContext context) {
return Container(
decoration: widget.boxDecor,
padding: widget.padding,
margin: widget.margin,
width: widget.width,
height: widget.height,
child: Center(
child: DropdownButton<String>(
value: widget.initialValue ?? dropdownValue,
icon: widget.iconDropdown,
isExpanded: true,
elevation: 16,
style: primaryColor400Style.copyWith(
fontSize: fontSize10,
),
underline: Container(
height: 2,
decoration: BoxDecoration(
color: Colors.transparent,
),
),
onChanged: (String? newValue) {
if (newValue != 'Personal') {
Provider.of<SelectedTeamProvider>(context, listen: false)
.setSelectedTeamNameForTicket(newValue!);
} else {
Provider.of<SelectedTeamProvider>(context, listen: false)
.setSelectedTeamNameForTicket('');
}
if (widget.onChanged != null) {
widget.onChanged!(newValue!);
}
setState(() {
dropdownValue = newValue!;
});
},
items: itemLists.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value.tr()),
);
}).toList(),
),
),
);
}
You can use menuMaxHeight to control the size of the menu.
child: DropdownButton<int>(
menuMaxHeight: 300, // <-- Adjust this value to get the right number of items
...
),

How to disable a specific dropdownmenu item value in flutter

Disable dropDown value in Flutter
policyDropdown = ['Platinum', 'Gold', 'Sr. Citizen'],
child: Container(
height: 50.0,
child: ListTile(
title: Text('Policy Type'),
trailing: DropdownButtonHideUnderline(
child: DropdownButton(
value: policyDropdownData,
items: policyDropdown.map((String value) {
return DropdownMenuItem(
child: Text(value),
value: value,
);
}).toList(),
onChanged: (String? value) {
setState(() {
policyDropdownData = value.toString();
});
},
),
disable the first data of the policyDropdown... What can I do?
You can use the enable property of the DropdownMenuItem and enable every other option than the first one of your policyDropdown list i.e."Platinum".
for example:
return DropdownMenuItem(
value: value,
child: Text(value),
enabled: value != 'Platinum',
);
Additionally, If you want users to know that the option is disabled you can change the color of the text using the same logic.
return DropdownMenuItem(
value: value,
child: Text(
value,
style: TextStyle(
color: value != 'Platinum'
? Colors.white
: Colors.white60,
),
),
enabled: value != 'Platinum',
);

Flutter how to set the value of the dropdown button programmatically

I m new to flutter, need help to set the value of the DropdownButton programmatically.
The value is from textfield. Once i click it, it will set the value at the dropdownbutton automatically.
Widget _districtListContainer() {
return Container(
width: 360.0,
child: new InputDecorator(
decoration: InputDecoration(
suffixIcon: new Icon(
Icons.search,
color: Colors.blue[700],
),
labelText: 'Select District',
labelStyle: TextStyle(fontSize: 12.0)),
isEmpty: _selectedDistrict == null,
child: new DropdownButtonHideUnderline(
child: new DropdownButton<District>(
value: _selectedDistrict,
isDense: true,
isExpanded: false,
onChanged: (District newValue) {
setState(() {
_selectedDistrict = newValue;
});
},
items: _listDistrict?.map((District value) {
return new DropdownMenuItem<District>(
value: value,
child: new Text(
value.district != null ? value.district : '',
style: new TextStyle(fontSize: 11.0),
),
);
})?.toList() ??
[],
),
),
),
margin: EdgeInsets.only(bottom: 10.0));
}
thanks
First Of All, Add the data into the list[] From the TextFormfield then retrieve the list into DropDownButton item.
Also, Make Sure, DropDown Button List Display Textformfield data insert activity could not be able to update simultaneously.

Flutter dropdown value if not selected, then assign the initial value

I have a DropDownButtonFormField I need to check this. If the dropdown value is not selected by the user then assign the initial value when submitting.
Custom DropDown
Container myDropDownContainer(String initialVal, List<String> listItems,
String text, Function myFunc, Function validate) {
return Container(
margin: const EdgeInsets.all(8),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(
width: 120,
child: Text(
text,
style: kTextStyle,
),
),
const SizedBox(
width: 20,
),
Expanded(
child: Container(
height: 50,
decoration: BoxDecoration(
color: Colors.orangeAccent,
borderRadius: BorderRadius.circular(5)),
child: DropdownButtonFormField<String>(
autovalidateMode: AutovalidateMode.always,
//menuMaxHeight: 300,
validator: (value) {
if(value!.isEmpty) {
return "485s4a8sd4as85";
}
} ,
decoration: const InputDecoration(border: InputBorder.none),
isExpanded: true,
onTap: () => myFunc,
//borderRadius: BorderRadius.circular(5),
value: initialVal,
icon: const Icon(
Icons.arrow_downward,
color: Colors.black38,
),
iconSize: 24,
elevation: 16,
dropdownColor: Colors.deepOrange,
style: kTextStyle.copyWith(color: Colors.black),
onChanged: (val) => myFunc(val),
items: listItems.map<DropdownMenuItem<String>>((String? val) {
return DropdownMenuItem(
//TODO: Set default values
value: val,
child: Text(
val,
style: kTextStyle.copyWith(color: Colors.black),
),
);
}).toList(),
),
),
)
],
),
);
}
This is my onChanged property that assigns the selected value by the user. I added some explanations about what I am trying to do.
String _valueCinsiyet = "Diğer"; // initial value
void onChangedCinsiyet(String? newVal) {
setState(() {
if(newVal==null) {
_formData.setCinsiyet(_valueCinsiyet);
/*
'if newVal is null' means that if the value is not selected by the user
then set the initialValue( _valueCinsiyet)
*/
} else {
/*
if newVal is not null then assign the newVal( which means the selected value)
into my initialValue, then set the data to use it on different pages. What is missing?
*/
_valueCinsiyet = newVal;
_formData.setCinsiyet(_valueCinsiyet);
}
});
}
You can use nullable data to track DropdownButtonFormField changes. Being nullable you can check if it is null or not, no need to anything extra on onChanged: just assign new value usual way.
On state before build method: String? value; // value to keep track
child: DropdownButtonFormField<String>(
value: value,
onChanged: (val) {
setState(() {
value = val;
});
},
Now onSaved/submit button you can pass value by checking null, simple way is
value?? "default Value". In your case, it is value??Diğer

How to open dropDownButton from RaisedButton

Using Flutter.
When a user taps a button, I want focus to shift to a dropDownButton and open up the options. Here is my attempt (not working):
RaisedButton(
onPressed: () {setState(() {FocusScope.of(context).requestFocus(_node);exactTime = false;});},
color: Theme.of(context).primaryColor,
child: const Text(
'Estimate',
style: TextStyle(fontSize: 20)
),
)
DropdownButton<String>(
isExpanded: true,
focusNode: _node,
items: ageRanges.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value, style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)),
);
}).toList(),
value: pmhOnset,
onChanged: (String selected) {
setState(() {
pmhOnset = selected;
});
},
)
I don't get any errors. It just doesn't do anything. Any suggestions?
From what I have read it is not possible with out making your own DropDownButton class but that shouldn't be that hard after all just a matter of coping most of flutters code and changing it to fit your need I'll attach a link that I think you will find helpful.