Flutter how to set the value of the dropdown button programmatically - flutter

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.

Related

Flutter Validate DropDownButton without using DropDownButtonFormField

Im trying to use a dropDownButton instead of a dropDownButtonFormField because i run thru alot of bugs that i see in the dropDownButtonFormField widget. One problem is that in dropDownButtonFormField the clickable area to open the items is only over the hint text and not a cm under it, witch in my case created bad ux. The second problem is that in the dropDownButtonFormField, if an item is a long text and the user presses it when it displays on the main part of the dropdown, the text doesnt create a new line so the user can see the text, the same thing doesnt happen to the dropDownButton widget. Im using dropDownButtonFormField only to use the validator. This is with using DropDownButton Widget.
And this is using the dropDownButtonFormField Widget while having a long text.
Center locationDropDown() {
return Center(
child: Container(
margin: const EdgeInsets.all(10),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
decoration: BoxDecoration(
color: Colors.grey.shade200,
borderRadius: BorderRadius.circular(12),
),
child: DropdownButtonFormField<String>(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please select a location';
}
return null;
},
decoration: const InputDecoration(
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.transparent),
),
),
value: chooseLocation,
hint: const Text('Select a location'),
isExpanded: true,
items: workingData!.map((some) {
return DropdownMenuItem(
child: Text(
some.name + ' (${some.location})',
),
value: some.id,
);
}).toList(),
onChanged: (String? displayedValue) {
setState(
() {
chooseLocation = displayedValue!;
},
);
},
),
),
);
}
isDense: false,
Add isDense value false in DropdownButtonFormField.

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

Flutter Prevent FutureBuilder from running twice

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),
);

Flutter Disable and Enable Button based on the user input on textfield

How can I disable a button when the user hasn't added any content to the textfield yet and then enable it once the user type something?
Is it possible? And if no is there another way to do it?
Thanks
return AlertDialog(
contentPadding: EdgeInsets.only(top: 5.0),
content: Padding(
padding: EdgeInsets.only(left: 15.0, right: 15.0, bottom: 20.0),
child: TextField(
keyboardType: TextInputType.multiline,
decoration: InputDecoration(labelText: 'Send a new message...'),
onChanged: (value) {
setState(() {
_newMessage = value;
});
},
),
),
actions: [
IconButton(
color: Colors.tealAccent,
icon: Icon(
Icons.navigate_next_rounded,
size: 40.0,
),
onPressed: _newMessage.trim().isEmpty ? null : _sendNewMessage,
),
],
);
To achive this you have to get the lenght of the input from the textfield, the correct way is to use a TextEditingController but for this simple purpose a workarount should do the job.
Code:
Initialize a new bool isInputEmpty before the return AlertDialog
onChanged: (value) {
setState(() {
_newMessage = value;
if(_newMessage.length > 0){ //add these lines
isInputEmpty = false;
} else {
isInputEmpty = true;
}
});
},
and to disable to button you can wrap him inside a IgnorePointer
IgnorePointer(
ignoring: isInputEmpty,
child: IconButton(...),
),
You can even change the button color:
IconButton(
color: isInputEmpty ? Colors.grey : Colors.tealAccent,
),
Use a Text Editing Controller https://flutter.dev/docs/cookbook/forms/text-field-changes
final controller = TextEditingController();
onPressed: controller.text.length==0 ? null : _sendNewMessage,
pls check if the .length is correct can't remember haha

How to add autofill dropdown in flutter?

I've made a dropdown of cities and city list is coming from API. When user clicks on GPS button, it will auto fill the dropdown field. How should I auto fill the city name in dropdown? I tried by using dropdown inside textfield
TextFormField(
controller: city,
decoration:InputDecoration(
border:InputBorder.none,
prefix: DropdownButtonFormField<String>(
decoration: InputDecoration.collapsed(
hintText: 'select',
hintStyle: TextStyle(fontSize: 12,color: Colors.grey.shade600),
),
value:type,
validator: (value) => value == null? 'please select': null,
onChanged: (String newValue) {
setState(() {
type = newValue;
});
},
items: List?.map((item){
return DropdownMenuItem(
onTap: (){
selectedCity=item['city'];
// print(selectedCity);
},
value: item['id'].toString(),
child: Padding(
padding: const EdgeInsets.only(left:15.0,top: 13.0),
child: Text(item['city'],style: TextStyle(fontSize: 12,color: Colors.grey.shade600),),
),
);
})?.toList()??[]
),
),
),
You can use ready-made auto-complete packages.
Some examples:
https://pub.dev/packages/autocomplete_textfield
https://pub.dev/packages/dropdownfield