Flutter - Radio button value is not getting selected - flutter

I have a radio buttons created but while on click of the buttons the value is not getting changed.
here is my code.
Widget _buildOmsIDTextField() {
// Group Value for Radio Button.
int id = 1;
List<OptionList> nList = [
OptionList(
padding : const EdgeInsets.fromLTRB(14.0, 180, 25, 50),
index: 1,
option: "Accept",
),
OptionList(
padding : const EdgeInsets.all(14.0),
index: 2,
option: "Reject",
),
];
return Column(
children: <Widget>[
const Padding(
padding : EdgeInsets.all(14.0),
child: Text("Please Select an Option", style: TextStyle(fontSize: 23))
),
SizedBox(
height: 150.0,
child: Column(
children:
nList.map((data) => RadioListTile(
title: Text(data.option),
groupValue: data.index,
value: id,
onChanged: (val) {
setState(() {
radioItemHolder = data.option ;
id = data.index;
});
},
)).toList(),
),
),
],
);
}
Any help would be highly appreciated!

While you are calling _buildOmsIDTextField() inside build method, the int id = 1; will always get 1. Put your group value outside the build method. And use same group value on radio buttons.
// Group Value for Radio Button. I also prefer putting any decleared varable for radio button here
int id = 1;
Widget _buildOmsIDTextField() {...
...
nList.map((data) => RadioListTile(
title: Text(data.option),
groupValue: id,
value: data.option,
}
#override
Widget build(BuildContext context) {
A better way of doing this, providing data type on RadioListTile.
OptionList? selectOption;
List<OptionList> nList = [
OptionList(
padding: const EdgeInsets.fromLTRB(14.0, 180, 25, 50),
index: 1,
option: "Accept",
),
OptionList(
padding: const EdgeInsets.all(14.0),
index: 2,
option: "Reject",
),
];
Widget _buildOmsIDTextField() {
return Column(
children: <Widget>[
const Padding(
padding: EdgeInsets.all(14.0),
child: Text("Please Select an Option",
style: TextStyle(fontSize: 23))),
SizedBox(
height: 150.0,
child: Column(
children: nList
.map((data) => RadioListTile<OptionList>(
title: Text(data.option),
groupValue: selectOption,
value: data,
onChanged: (val) {
setState(() {
selectOption = val;
});
},
))
.toList(),
),
),
],
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: _buildOmsIDTextField(),
);
}

Related

when we click on dropdown than we are not able to scroll the screen and text field is hide behind of keyboard in flutter

as you can see in the image I want to scroll the screen but cannot do this when the keyboard is open.
like our search result/ list is hidden behind the keyboard.
for this, I am using SingleChildScrollView, and it's working when the keyboard or dropdown is not active. when we click on dropdown or edit in the search field then it's not working.
i want to scroll the screen even keyboard is open and search field is active.
ListTileTheme(
dense: true,
contentPadding: EdgeInsets.only(left: 25, right: 25),
child: Form(
key: _formKey,
child: Padding(
padding:
EdgeInsets.only(left: 25, right: 25, top: 10),
child: Column(
children: [
Padding(
padding:
EdgeInsets.only(top: 0, bottom: 20),
child: Row(
children: [
Text(
"CONTACT",
style: TextStyle(
color: AppColor.softBlue,
fontSize: 13,
fontFamily: FontFamily
.montserratSemiBold),
),
Spacer()
],
),
),
Column(
children: [
ProfileWrapDataWithTitle(
title: "City",
),
SearchDropdownInputs(
maxHeight: 250,
modes: Mode.MENU,
dropdownHintText: widget
.salesFreshProfileData?.city
.toString() ??
"",
dropdownItem:
_selectCityData!.map((city) {
return city.cityName.toString();
}).toList(),
dropdownOnChanged: (city) {
setState(() {
_city = city.toString();
updateCity(city_name: _city);
});
},
dropdownSelectedItem: _city,
dropdownItemSuggestion:
(context, item, isSelected) {
return DropdownSuggestionItem(
dropdownPopup: item.toString(),
);
},
),
],
),
SizedBox(
height: 20,
),
Column(
children: [
ProfileWrapDataWithTitle(
title: "Project",
),
SearchDropdownInputs(
maxHeight: 250,
modes: Mode.MENU,
dropdownHintText: procheck.toString(),
dropdownItem:
_selectProjectData!.map((project) {
return project.projectName.toString();
}).toList(),
dropdownOnChanged: (pro) {
setState(() {
project = pro.toString();
print(
"this is updated project{$project}");
updatepPro(project_name: project);
});
},
dropdownSelectedItem: project,
dropdownItemSuggestion:
(context, item, isSelected) {
return DropdownSuggestionItem(
dropdownPopup: item.toString(),
);
},
),
],
),
SizedBox(
height: 20,
),
Column(
children: [
ProfileWrapDataWithTitle(
title: "Lead Stage",
),
SearchDropdownInputs(
modes: Mode.MENU,
maxHeight: 180,
dropdownHintText: "Select Lead Stage",
dropdownItem: _leadStatusConditionData!
.map((leadStatus) {
return leadStatus.statusName
.toString();
}).toList(),
dropdownOnChanged: (leadStatus) {
setState(() {
_selectLeadStatus =
leadStatus.toString();
if (_leadStatusConditionData !=
null) {
for (int index = 0;
index <
_leadStatusConditionData!
.length;
index++) {
LeadStatusCondition
leadConditionObject =
_leadStatusConditionData![
index];
if (_selectLeadStatus ==
leadConditionObject
.statusName) {
leadConditionId =
leadConditionObject
.statusId
.toString();
}
// reason(leadStatus);
}
}
_leadStatusReasonData?.length = 0;
reason(leadStatus);
});
},
// data in this
dropdownSelectedItem: leadStatus =
_selectLeadStatus,
dropdownItemSuggestion: (
context,
item,
isSelected,
) {
return DropdownSuggestionItem(
dropdownPopup: item.toString(),
);
},
),
],
),
// ]
],
),
),
),
),

How to get DropdownButtonFormField value with a button click - Flutter

I am trying to develop a survey form using Flutter and I have multiple dropdown fields in the form. I want to get the selected values from those dropdowns when I click the save button. But all I am getting is the value I initially set inside initState(). The code I am using is as below. Any help to get this sorted out is much appreciated.
class _EditSurveyState extends State<EditSurvey> {
String contactMethod;
String country;
List contactMethodList = ['phone', 'email', 'mail'];
List countryList = ['us', 'uk', 'germany'];
#override
void initState() {
super.initState();
contactMethod = surveryData['contact'];
country = surveryData['country'];
}
#override
Widget build(BuildContext context) {
return Scaffold(
return Scaffold(
children: [
Expanded(
flex: screenWidth(context) < 1300 ? 10 : 8,
child: SafeArea(
child: Column(
children: [
createDropdownField("Contact", contactMethod, contactMethodList),
createDropdownField("Country", country, countryList),
Row(mainAxisAlignment: MainAxisAlignment.end,
children: [
ElevatedButton(
onPressed: () async {
print(contactMethod + country);
},
style: ElevatedButton.styleFrom(
padding: EdgeInsets.symmetric(horizontal: 50),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)
)
),
child: Text(
"UPDATE",
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
)
),
],
),
]
)
)
)
]
)
);
}
Row createDropdownField(String labelText, String _valueChoose, List valueList) {
return Row (
children: [
SizedBox(height: 25,),
Align(
alignment: Alignment.centerLeft,
child: Text(
'$labelText',
),
),
DropdownButtonFormField(
value: _valueChoose,
hint: Text("$labelText"),
icon: Icon(Icons.arrow_drop_down),
isExpanded: true,
onChanged: (newValue){
setState(() {
_valueChoose = newValue;
});
},
items: valueList.map((valueItem){
return DropdownMenuItem(
value: valueItem,
child: Text(valueItem),
);
}).toList(),
),
],
);
}
}
I don't understand why you using intitstate if you want to initialize value to String you can do it while declaring, try removing initstate and
Declare a variable first where you will store new value from dropdown onchange
i.e
class _EditSurveyState extends State<EditSurvey> {
String _currentValue;
DropdownButtonFormField(
onChanged: (val) =>
setState(() => _currentValue = val as String),
value: _currentValue ,
items: YourList.map((item) {
return DropdownMenuItem(
value: item,
child: Text('$item Items'),
);
}).toList(),
),

How can I add a button inside a dropdownButton in Flutter

I just started learning flutter, I have programming knowledge before, but I am just getting used to the widget structure. What I want to do is add a button to the last element of the DropdownButton list and I used the DropdownMenuItem widget to do that. And I used Text as child and I put Button in the last element. The problem is, I can't give Text to the value property of the DropdownButton. That's why I'm getting an error because I've given a value that isn't in items [ ]. Is there any way I can get the value of the Text widget? Or can I do it another way? I hope I was explanatory.
code:
class _TodoPageState extends State<TodoPage> {
Text dropdownValue = Text('123'); // **FOR DEFAULT VALUE**
#override
Widget build(BuildContext context) {
return SafeArea(
child: Center(
child: Column(
// mainAxisAlignment: MainAxisAlignment.center,
// crossAxisAlignment: CrossAxisAlignment.center,
children: [
MyTabBar(),
Row(
children: [
Expanded(
child: Container(
margin: EdgeInsets.only(left: 3, top: 5),
child: Row(
children: [
Ink(
width: 152,
height: 45,
padding: EdgeInsets.all(6),
decoration: BoxDecoration(
border: Border.all(color: Colors.black, width: 2),
borderRadius: BorderRadius.circular(10),
),
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
value: dropdownValue, **// CANT SET THE DEFAULT VALUE**
isExpanded: true,
icon: Image.asset('assets/down-list-arrow.png'),
iconSize: 10,
elevation: 16,
onChanged: (newValue) {
setState(() {
dropdownValue = newValue!; **// CANT SET THE DEFAULT VALUE**
});
},
items: [
DropdownMenuItem(child: Text('123'), value: ''),
DropdownMenuItem(child: Text('123'), value: ''),
DropdownMenuItem(
child: TextButton(
child: Text('Create'),
onPressed: () {},
))
],
),
),
)
],
),
),
),
],
),
MyListView()
],
),
));
}
}
I found 2 ways: Assigning create on values or check new value before assigning on onChanged and using FocusNode.
Test Widget
class TodoPage extends StatefulWidget {
TodoPage({Key? key}) : super(key: key);
#override
_TodoPageState createState() => _TodoPageState();
}
class _TodoPageState extends State<TodoPage> {
late String selectedValue; // **FOR DEFAULT VALUE**
late String selectedValue2;
List<String> dropDownItemValue = ['123', '2', '4', 'Create'];
List<String> dropDownItemValue2 = ['xx', '2', '4'];
late final dropDownKey2;
final FocusNode dropDownFocus = FocusNode();
#override
void initState() {
super.initState();
///selected value must be contain at dropDownItemValue
selectedValue = dropDownItemValue[0];
selectedValue2 = dropDownItemValue2[0];
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: Colors.deepPurple,
body: Center(
child: Column(
// mainAxisAlignment: MainAxisAlignment.center,
// crossAxisAlignment: CrossAxisAlignment.center,
children: [
// MyTabBar(),
DropdownButtonHideUnderline(
child: DropdownButton<String>(
value: selectedValue, // CANT SET THE DEFAULT VALUE**
isExpanded: true,
// icon: Image.asset('assets/down-list-arrow.png'),
iconSize: 10,
elevation: 16,
onChanged: (newValue) {
print(newValue);
setState(() {
selectedValue = newValue!; // SET THE DEFAULT VALUE**
});
},
/// dont assing same value on multiple widget
items: List.generate(
dropDownItemValue.length,
(index) => DropdownMenuItem(
child: Text('${dropDownItemValue[index]}'),
value: '${dropDownItemValue[index]}'),
),
),
),
SizedBox(
height: 100,
),
DropdownButtonHideUnderline(
child: DropdownButton<String>(
focusNode: dropDownFocus,
value: selectedValue2, // CANT SET THE DEFAULT VALUE**
isExpanded: true,
// icon: Image.asset('assets/down-list-arrow.png'),
iconSize: 10,
elevation: 16,
onChanged: (newValue) {
print(newValue == null);
// if value doesnt contain just close the dropDown
if (newValue == null) {
dropDownFocus.unfocus();
} else
setState(() {
selectedValue2 = newValue; // SET THE DEFAULT VALUE**
});
},
/// dont assing same value on multiple widget
items: List.generate(
dropDownItemValue2.length + 1,
(index) => index < dropDownItemValue2.length
? DropdownMenuItem(
child: Text('${dropDownItemValue2[index]}'),
value: '${dropDownItemValue2[index]}')
: DropdownMenuItem(
child: TextButton(
child: Text('Create'),
onPressed: () {},
),
),
),
),
),
],
),
),
));
}
}

Flutter web, weired results after Consumer rebuild

I have a Form in flutter, containing a column with rows with textFormFields.
Each row has a iconButton at the end for deleting said row. The rows is built with a Consumer.
I have a notifier class containing data that the consumer listens for.
When the delete button is pressed a function in the notifier class is called, responsible for deleting the row with the given index. The same function is printing out the dataset befor deletion and again after deletion. The print looks good, the result is as expected.
The Consumer also rebuilds the dataset with one row less. But the data that is presented in the ui is not as expected.
In the Widget that is responsible for building the rows I print out the data that is put in the initialValue of the textFormField. The print looks good, again as expected. But the ui does not render what the print is showing.
See pictures and code.
Ready for deleting the second row:
After deletion:
Code that deletes the row and prints the data.
void deletePoint({int switchpointIndex, int pointIndex, Point point}) {
for (Switchpoint switchpoint in _settings.switchpoints) {
for (Point point in switchpoint.points) {
print("Tag: ${point.tag}. And Type: ${point.type}");
}
}
_settings.switchpoints[switchpointIndex].points.removeAt(pointIndex);
for (Switchpoint switchpoint in _settings.switchpoints) {
for (Point point in switchpoint.points) {
print("Tag: ${point.tag}. And Type: ${point.type}");
}
}
notifyListeners();
}
Result of the print (as expected):
Tag: a. And Type: a
Tag: b. And Type: b
Tag: c. And Type: c
Tag: a. And Type: a
Tag: c. And Type: c
Code that prints and renders the data in the row Widget:
#override
Widget build(BuildContext context) {
print("PointIndex: $pointIndex, value: ${point.tag} and ${point.type}");
return Row(
...
TextFormField(
...
initialValue: point.tag ?? ''
...
TextFormField(
...
initialValue: point.type ?? ''
...
This also prints the expected:
PointIndex: 0, value: a and a
PointIndex: 1, value: c and c
Anyone who understands whats going on?
-- EDIT --
No TextEditingController.
Form code:
return Container(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 50,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Switchpoint Layout',
style: TextStyle(
color: Colors.teal,
fontSize: 20,
fontWeight: FontWeight.bold),
),
TextButton.icon(
onPressed: () {
context
.read<SettingsNotifier>()
.addEmptySwitchpoint();
},
icon: Icon(Icons.add),
label: Text('Add Switchpoint')),
],
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Consumer<SettingsNotifier>(
builder: (context, notifier, child) {
List<SwitchpointRow> switchpointRows = [];
int switchpointIndex = 0;
for (Switchpoint switchpoint
in notifier.switchPoints) {
switchpointRows.add(SwitchpointRow(
switchpoint: switchpoint,
switchpointIndex: switchpointIndex,
formKey: _formKey,
));
switchpointIndex++;
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: switchpointRows),
],
);
}),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: ElevatedButton(
onPressed: () async {
print(context
.read<SettingsNotifier>()
.settings
.toJson());
if (_formKey.currentState.validate()) {}
},
child: Text('Submit'),
),
),
],
),
),
);
SwitchpointRow code:
class SwitchpointRow extends StatelessWidget {
const SwitchpointRow({
Key key,
#required this.switchpoint,
#required this.switchpointIndex,
#required this.formKey,
}) : super(key: key);
final int switchpointIndex;
final Switchpoint switchpoint;
final formKey;
List<PointRow> loadPoints(List<Point> points) {
List<PointRow> pointRows = [];
int pointIndex = 0;
for (Point point in points) {
pointRows.add(PointRow(
point: point,
switchpointIndex: switchpointIndex,
pointIndex: pointIndex,
last: points.last == point ? true : false));
pointIndex++;
}
return pointRows;
}
#override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: const EdgeInsets.only(bottom: 20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
AppBar(
backgroundColor: Colors.amberAccent,
title: TextFormField(
decoration: InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.fromLTRB(0, 2, 0, 4),
isDense: true,
hintText: 'Switchpoint name',
labelText: 'Switchpoint name',
),
initialValue: switchpoint.name ?? '',
onChanged: (value) {
context
.read<SettingsNotifier>()
.switchPoints[switchpointIndex]
.name = value;
},
validator: (value) {
if (value.isEmpty) {
return 'mandatory';
}
return null;
}),
actions: [
Padding(
padding: const EdgeInsets.only(right: 18.0),
child: TextButton.icon(
onPressed: () {
context.read<SettingsNotifier>().deleteSwitchpoint(
switchpointIndex: switchpointIndex);
},
icon: Icon(Icons.delete),
label: Text('Delete Switchpoint'),
),
),
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: TextButton.icon(
onPressed: () {
context
.read<SettingsNotifier>()
.addPoint(switchpointIndex);
},
icon: Icon(Icons.add),
label: Text('Point'),
),
),
],
),
Padding(
padding: const EdgeInsets.only(left: 50.0),
child: Column(children: loadPoints(switchpoint.points)),
),
],
),
),
);
}
}
PointRow code:
class PointRow extends StatelessWidget {
const PointRow(
{Key key,
#required this.point,
#required this.switchpointIndex,
#required this.pointIndex,
#required this.last})
: super(key: key);
final Point point;
final int pointIndex;
final int switchpointIndex;
final bool last;
#override
Widget build(BuildContext context) {
print("PointIndex: $pointIndex, value: ${point.tag} and ${point.type}");
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
flex: 3,
child: TextFormField(
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(0, 2, 0, 4),
isDense: true,
hintText: 'Tag',
labelText: 'Point tag',
),
onChanged: (value) {
context
.read<SettingsNotifier>()
.switchPoints[switchpointIndex]
.points[pointIndex]
.tag = value;
},
initialValue: point.tag ?? '',
validator: (value) {
if (value.isEmpty) {
return 'mandatory';
}
return null;
}),
),
SizedBox(width: 30.0),
Expanded(
flex: 3,
child: TextFormField(
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(0, 2, 0, 4),
isDense: true,
hintText: 'Type',
labelText: 'Type of point',
),
onChanged: (value) {
context
.read<SettingsNotifier>()
.switchPoints[switchpointIndex]
.points[pointIndex]
.type = value;
},
initialValue: point.type ?? '',
),
),
Expanded(
child: IconButton(
padding: EdgeInsets.all(0.0),
icon: Icon(Icons.delete),
onPressed: () {
context.read<SettingsNotifier>().deletePoint(
switchpointIndex: switchpointIndex,
pointIndex: pointIndex,
point: point);
},
),
)
],
);
}
}
The whole Form picture:
So, after some trial and error the solution had to be a TextEditingController which I wanted to avoid since eventually there will be several fields.
So the solution is a inline controller like this:
TextFormField(
...
controller: TextEditingController()..text = 'the value',
...
);
In this way the UI behaves as I want.

How to access a specific value from a Map <Object> flutter

Need to access a single value when the item is selected in the list.
When the item is clicked, it prints the whole list of objects, instead the value of the selected object.
For example, when user selects Spanish, should print SP instead of the list of objects.
I have a class and a list for the languages, but for this question is not relevant.
This is what I have achieved so far:
List <Object> Dictionary = [
{'Spanish': 'SP'},
{'Italian': 'IT'},
{'German': 'DE'},
{'Arab': 'AR'},
{'Greek': 'GR'},
{'Thai': 'TH'},
{'Chinese': 'CH'},
{'French': 'FR'}
];
List<Language> newDataList;
final finalList = dictionary.values.toList();
onItemChanged(String value) {
setState(() {
newDataList = languages.where((lang) => lang.title.toLowerCase().contains(value.toLowerCase())).toList();
});
}
#override
initState() {
super.initState();
newDataList = [...languages];
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(12.0),
child: TextField(
controller: _textController,
decoration: InputDecoration(
icon: Icon(Icons.search),
hintText: 'Type languages',
),
onChanged: onItemChanged,
),
),
Expanded(
child: ListView(
padding: EdgeInsets.all(12.0),
children: newDataList.map((data) {
return Ink(
color: data.selected ? TheBaseColors.lightGreen : Colors.transparent,
child: ListTile(
title: Text(data.title),
onTap: () {
setState(() {
data.selected = !data.selected;
print("${data.title} is now ${data.selected ? "selected" : "not selected"}");
print(Dictionary);
});
}),
);
}).toList(),
),
),
Expanded(
child: Column(children: [
Text('Selected languages :'),
Expanded(
child: ListView(
children: newDataList.where((l) => l.selected).map((l) => Padding(child: Text(l.title), padding: EdgeInsets.only(right: 10))).toList()))
]))
],
),
);
}
}
Tried dictionary.value, dictionary[value]
Instead of List<Object> you want to use Map<String, String> for this.
Map<String, String> dictionary = {
'Spanish': 'SP',
'Italian': 'IT',
'German': 'DE',
'Arab': 'AR',
'Greek': 'GR',
'Thai': 'TH',
'Chinese': 'CH',
'French': 'FR'
};
If you use this you can easily do dictionary['Spanish'] and receive 'SP' as value.