Group radio button in listView - flutter

How to use group button in listView ? In each row, it has two radio button.
The problem now is if I select one of the radio button , the radio button not showing it is selected.
int value;
Map<int, bool> answers = {};
String _radioValue;
String choice;
int count = 0;
...item['questions']
.asMap()
.entries
.map((items) {
count++;
return TableRow(children: [
Padding(
padding: EdgeInsets.all(10),
child: Text(items.value['name'])),
Row(
children: [
Radio(
value: items.value['id'],
groupValue: count,
onChanged: (val) {
setSelectedRadioTile(val);
},
),
Text("Yes"),
Radio(
value: items.value['id'] + count,
groupValue: count,
onChanged: (val) {
setSelectedRadioTile(val);
},
),
Text("N/A")
],
)
]);
}).toList()
setSelectedRadioTile(int val) {
print(val);
setState(() {
count = val;
});
}

Okay well I have built you a working version based on what you provided here. Please keep in mind that it would probably be a good idea to look at the documentation more in-depth so you get a feeling of how some widgets behave and what specific properties (like groupValue) are for. Also keep in mind that the following code is not optimised or whatsoever, I just got it worked out for your case - thinking about how to structure your data overall is some fundamental thing you should take a look at. Maybe try some out some flutter courses which are available or look at some youtube content from known flutter coders. But now back to some code stuff.
I used those properties in my StatefulWidget to work with. Since you use some kind of question map and I don't know how it looks like, I just used something bare bones:
/// Map which has the question ID as its key and the answer from the user (currently true for yes and false for no (or n/a as in your case)
Map<int, bool> _answers = {};
/// Map which holds the information of your questions. Right now only an ID to be able to reference it and the actual question - again very bare bones
Map<String, dynamic> _item = {
'questions': [
{
'id': 0,
'question': 'Is this legit?',
},
{
'id': 1,
'question': 'Oh really?',
},
]
};
Then the method which will be called by the Radio widget once onChanged is triggered:
/// We need to know which question has been answered (therefore the ID) and which (bool) answer has been clicked by the user
_setSelectedRadioTile(int id, bool answer) {
setState(() {
_answers[id] = answer;
});
}
And now the widget part - since your code starts where you iterate over the questions, I also share this part specifically:
/// Since the map itself is typed as <String, dynamic>, accessing 'questions' will return dynamic. Only we, as we know the structure, know that this is indeed a list. Therefore we need to cast this as "List<dynamic>" so we can iterate over it and won't get exceptions
(_item['questions'] as List<dynamic>)
.map(
(question) => TableRow(children: [
Padding(
padding: EdgeInsets.all(10),
child: Text(question['question'])),
Row(
children: [
Radio(
/// The [value] property of Radio tells us, which property is used in [onChanged] - therefore now once this Radio is clicked, true is provided in the [onChanged] callback
value: true,
/// [groupValue] is the value which this Radio is bound to. As you probably know, only one Radio button should be active for a group. So if you have a question which has several possible answers as radio buttons, we only want one of them to be active at a time. Thats what the [groupValue] is for. Since we iterate over all questions and every entity of a question (currently) has two possible answers (Yes and N/A), both those answers are for a specific question - the question with the current ID
groupValue: _answers[question['id']],
onChanged: (answer) {
_setSelectedRadioTile(question['id'], answer);
},
),
Text("Yes"),
Radio(
value: false,
groupValue: _answers[question['id']],
onChanged: (answer) {
_setSelectedRadioTile(question['id'], answer);
},
),
Text("N/A")
],
)
]),
)
.toList(),
This should work on your side once you updated this example to fit with your data model. Again: I advise you to think about how you structure your data generally.

Related

How do i modify the data of an existing variable in flutter?

I want to make an editable TextWidget in flutter but I don't really know how to go around it, I did some research, but still can't find a good solution.
Here's my sample code below.
I have a variable called
int qty = 1;
and so I called the variable in TextWidget
Column(
children: [
Text(
"${qty}",
style: TextStyle(),
)
],
),
I want to have these features that make user tab on the value to change it if they want, upon tap, a pop-up dialog will show to give the user the ability to change the existing value to whatever the user wants.
Please if anyone knows how, please help.
You will need a statfull widget to call setState and make the UI update with the new value stored in your qty variable. (I'am assuming that you are not using any state managment).
I wrote a possible solution for what you need.
Let look into some considerations:
Text will show whatever is in the qty as long we call setState after (or do it inside) we change the value of qty.
You need some widget to detect your tap. If you want to the text be 'clicable' then it should be wraped inside that widget.
The onTap/onPress call back of that widget should show a new widget. For this you can use the already made showDialog() and pass it a Dialog Widget. in here you will put your ui for that.
In some point of that UI you need to introduce the new value. So you can use a simple TextField that will save the introduced value, where you can assign it to qty, without forgetting to call setState! Note that it deal with strings, so you neet to do an int.parse() ou double.parse accordingly to you qty var type.
And I think that's it.
The could be other ways of doing it. This is a good and simple approach for your need.
I wrote a piece of code to help or somelse how is trying to do it:
InkWell(
// can be gesture detector, button, etc
onTap: () => showDialog(
context: context,
builder: (context) => Dialog(
child: Container(
color:
Colors.white60, // change it accordingly to you
height: 80, // change it accordingly to you
width: 200, // change it accordingly to you
child: Column(
children: [
const Text('Change your value here'),
TextField(
decoration:
InputDecoration(hintText: qty.toString()),
onChanged: (insertValue) => setState(() {
qty = int.parse(insertValue);
}),
// you can use other callBack function (like onComplete,
// onSaved), wich is more eficient than calling setState eveytime,
// but you have to do the needed adtaptions. Like onSave
// needs a key to call the save function. is easy just google it.
),
],
)),
)),
child: Text(
"${qty}",
),
),
What you are probably looking is a DropdownButton.
You would have something like this:
int qty = 1;
List<int> listOfValues = [1,2,3,4];
and then in your column you would have
DropdownButton<int>(
// This are the list of items that will appear in your dropdown menu.
// items is all the options you want your users to be able to select from,
// and it take a list of `DropdownMenuItem`. So instead of creating a `DropdownMenuItem`
// for each of the items in `listOfValues`, we iterate through it and return
// a `DropdownMenuItem`
items: listOfValues
.map((item) => DropdownMenuItem<int>(
value: item,
child: Text('$item'),
))
.toList(),
value: qty,
onChanged: (value) {
if (value != null) {
setState(() {
qty = value;
});
}
},
),
For more information on DropDownButton, check the following links:
https://api.flutter.dev/flutter/material/DropdownButton-class.html
https://www.youtube.com/watch?v=K8Y7sWZ7Q3s
Note: In a scenario where you want to increase the quantity of an item, like in a shopping cart, maybe having a button increment qty by 1 would be better.

onChange does not get called for the PrefChoice in Flutter

I am using the flutter pref library to create a settings page. The PrefChoice is used to show a drop down for language selection. The drop down shows the values properly. Issue is when we select anything from the drop down, the onChange method does not get called for some reason. Due to this we are not able to take action on the change in choice. Is there anything I am missing here?
PrefChoice<String>(
title: Text(AppLocalization.of(context, 'settings.language')),
pref: 'language_key',
items: const [
DropdownMenuItem(
value: LocaleConstants.LC_ENGLISH,
child: Text(LocaleConstants.ENGLISH)),
DropdownMenuItem(
value: LocaleConstants.LC_GERMAN,
child: Text(LocaleConstants.GERMAN))
],
onChange: (value) {
// This never gets called
log.d('Locale changed to - $value');
},
),

Flutter DropDownButton value not changing after selecting a new value

I have been trying to make an external UI that a user can use to make certain changes to a database(dynamodb) in the cloud. When I select a new value, I want it to show the change that the user wants to make, without actually changing the database. The changes are saved only when I press a button on the appbar. Also when I use setState to rebuild the button, the value doesn't change on the cloud and it also changes the value for all of the buttons in the column(works fine without a setState). The code that I have provided changes the database when I press the save icon, but the drop-down button value stays the same unless I refresh the page. I apologize if I haven't explained my issue clearly enough, this is my first time posting on Stackoverflow, and I'm still learning about how to work with flutter and aws amplify.
body: InteractiveViewer(
constrained: false,
child: DataTable(
columns: [
DataColumn(label: Text('Apt #')),
DataColumn(label: Text('Type')),
DataColumn(label: Text('Availability')),
DataColumn(label: Text('Price')),
DataColumn(label: Text('Area'))
],
rows: aprts.map<DataRow>((element) { //aprts is a list that contains apartment objects.
return DataRow(cells: [
DataCell(Text(element.aptNum.toString())),
DataCell(Text(element.type)),
DataCell(DropdownButton<String>( /// this is the part im having problems wi
value: element.availabily, // gets the value for the availability attribute for the element and stores it into value.
onChanged: (String newValue) {
availValue = newValue; //stores the newValue in a global variable that is used in a function that is used toactually make changes to the database.
tempAvail = element;
},
items: <String>['AVAILABLE', 'SOLD', 'RESERVED']
.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
)), // end of problem.
DataCell(TextField(
controller: TextEditingController()
..text = element.price.toString(),
onChanged: (text) {
aptPrice = text;
tempPrice = element;
},
)),
DataCell(TextField(
controller: TextEditingController()..text = element.area,
onChanged: (text) {
aptArea = text;
tempArea = element;
},
)),
]);
}).toList()),
),
What the app looks like. After pressing the button
Use
onChanged: (String newValue) {
setState(() {
availValue = newValue;
tempAvail = element;
}
)
},
because for every change in the UI you must call setState((){})

Dropdown box not displaying selected value

When I select a value from my dropdown the hint text does not change:
String fontSizeValue;
new DropdownButton<String>(
items: new List<double>.generate(72, (i) => i + 2.0).map((double value) {
return new DropdownMenuItem<String>(
value: value.toString(),
child: new Text(value.toString()),
);
}).toList(),
onChanged: (String _) {
setState(() {
fontSize = double.parse(_);
fontSizeValue = _;
print(fontSizeValue);
});
},
value: fontSizeValue,
hint: Text('Select'),
)),
],
),
),
);
Any idea how I can get the selected value to show instead of "select"? Thanks
You did not post enough code, but I'll take a wild guess anyway, because there are a lot of questions with this problem:
Your variable String fontSizeValue; is defined locally, probably in the build function.
You have to define it in a wider scope, so it will retain it's value after another call to build that will happen when you call setState. Probably as a class member of your State class.

How can I create a conditional sentence for each key in a DropDownMenu map?

I know this can be hella standard for most of you guys, but I'm pretty new with Dart and I'm having trouble to find out a way to create a if-else statement for each key in this map I made.
This '_ramoAtividade' holds the key/value for a DropDownMenu, where the user select an item. As you can observe, each key holds a specific double value, and I want to set a exclusive if-else statement depending on the calculations I get by this function.
If the user choose "Industrial" in the DropDownMenu, and the calculation of 'debCalc' return less than the "Industrial" value (2.5), then it should return "User not allowed to promotion", but if the result of 'debCalc' is more than the selected item in the DropDownMenu, then it returns "User allowed to promotion".
To get the list of DropdownMenuItems for a Map<String, dynamic> map = {somedata} dynamically, use:
List<DropdownMenuItem>[
for(final String key in map.keys) DropdownMenuItem(
value: map[key],
child: Text(key),
);
]
Your onChanged function:
onChanged: (double newValue) {
// do the necessary calculations with your value
},
final code for your button:
DropdownButton<double>(
onChanged: (double newValue) {
// do the necessary calculations with your value
debCalc(newValue);
},
items: <DropdownMenuItem<double>>[
for(final String key in _ramoAtividade.keys) DropdownMenuItem<double>(
value: map[key],
child: Text(key),
);
],
),