I have a list of objects called options
List<Map<String, dynamic>> options = [
{"name": "usually", "value": 100, "id": 1},
{"name": "sometimes", "value": 70, "id": 2},
{"name": "rarely", "value": 40, "id": 3},
{"name": "never", "value": 0, "id": 4},
];
also, I have another list called questions
late List<Map<String, dynamic>> questions = [
{"id": 1, "name": "Q1", "options": options},
{"id": 2, "name": "Q2", "options": options},
{"id": 3, "name": "Q3", "options": options},
{"id": 4, "name": "Q4", "options": options},
{"id": 5, "name": "Q5", "options": options},
{"id": 6, "name": "Q6", "options": options},
{"id": 7, "name": "Q7", "options": options},
{"id": 8, "name": "Q8", "options": options},
{"id": 9, "name": "Q9", "options": options},
{"id": 10, "name": "Q10", "options": options},
{"id": 11, "name": "Q11", "options": options},
{"id": 12, "name": "Q12", "options": options},
{"id": 13, "name": "Q13", "options": options},
{"id": 14, "name": "Q14", "options": options},
];
How can I perform multi select for each question which allow the user select one option per one question ?
Code for the UI
return Scaffold(
body: Column(
children: [
Expanded(
child: ListView.separated(
itemCount: questions.length,
separatorBuilder: (context, index) {
return Divider();
},
itemBuilder: (context, index) {
return ListTile(
title: Text(questions[index]['name']),
subtitle: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: List.generate(
questions[index]['options'].length,
(lowerIndex) => Padding(
padding: const EdgeInsets.all(5.0),
child: InkWell(
onTap: () =>
ChoicesHelper.addValueToSelectedValuesList(
questions[index]['options'][lowerIndex]
['value'],
questions[index]['id'],
questions[index]['options'][lowerIndex]
['id']),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 20,
height: 20,
color: Colors.grey ),
SizedBox(width: 1),
Text(questions[index]['options']
[lowerIndex]['name'])
])))),
),
);
},
),
),
ElevatedButton(
onPressed: () {
ChoicesHelper.calculateResults();
},
child: Text('Calculate')),
],
),
);
Code for the methods in another class
static List<int> selectedValues = [];
static List<Map<String, dynamic>> answeredQuestionsIds = [];
static void addValueToSelectedValuesList(int value, int questionID, optionID) {
selectedValues.add(value);
answeredQuestionsIds.add({"questionID": questionID,"optionID": optionID});
}
As you can see, I just need to select one box for each question and turn it's color to red, but the problem is that all the row for single question is selected and all the boxes turns into red.
How can I select only one option for one question ?
CodePudding user response:
try this:
class ListWidget extends StatefulWidget {
const ListWidget({Key? key}) : super(key: key);
@override
State<ListWidget> createState() => _ListWidgetState();
}
class _ListWidgetState extends State<ListWidget> {
late List<Map<String, dynamic>> questions = [
{"id": 1, "name": "Q1", "options": options},
{"id": 2, "name": "Q2", "options": options},
{"id": 3, "name": "Q3", "options": options},
{"id": 4, "name": "Q4", "options": options},
{"id": 5, "name": "Q5", "options": options},
{"id": 6, "name": "Q6", "options": options},
{"id": 7, "name": "Q7", "options": options},
{"id": 8, "name": "Q8", "options": options},
{"id": 9, "name": "Q9", "options": options},
{"id": 10, "name": "Q10", "options": options},
{"id": 11, "name": "Q11", "options": options},
{"id": 12, "name": "Q12", "options": options},
{"id": 13, "name": "Q13", "options": options},
{"id": 14, "name": "Q14", "options": options},
];
List<Map<String, dynamic>> options = [
{"name": "usually", "value": 100, "id": 1},
{"name": "sometimes", "value": 70, "id": 2},
{"name": "rarely", "value": 40, "id": 3},
{"name": "never", "value": 0, "id": 4},
];
List<Question> _questions = [];
@override
void initState() {
super.initState();
_questions = questions.map((e) => Question.fromJson(e)).toList();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: _questions.length,
itemBuilder: (context, index) {
return _buildQuestion(
_questions[index],
(int? value) {
print("cvalue = ${value}");
var q = Question(
name: _questions[index].name,
id: _questions[index].id,
options: _questions[index].options,
groupValue: value!);
setState(() {
_questions[index] = q;
});
},
);
}),
);
}
_buildQuestion(Question question, Function(int?)? onChanged) {
return Row(
children: [
Expanded(
child: RadioListTile<int?>(
contentPadding: EdgeInsets.zero,
dense: true,
visualDensity: VisualDensity(horizontal: -4),
title: Text(question.options[0].name),
value: question.options[0].value,
groupValue: question.groupValue,
onChanged: onChanged),
),
Expanded(
child: RadioListTile<int?>(
contentPadding: EdgeInsets.zero,
dense: true,
visualDensity: VisualDensity(horizontal: -4),
title: Text(question.options[1].name),
value: question.options[1].value,
groupValue: question.groupValue,
onChanged: onChanged),
),
Expanded(
child: RadioListTile<int?>(
contentPadding: EdgeInsets.zero,
dense: true,
visualDensity: VisualDensity(horizontal: -4),
title: Text(question.options[2].name),
value: question.options[2].value,
groupValue: question.groupValue,
onChanged: onChanged),
),
Expanded(
child: RadioListTile<int?>(
contentPadding: EdgeInsets.zero,
dense: true,
visualDensity: VisualDensity(horizontal: -4),
title: Text(question.options[3].name),
value: question.options[3].value,
groupValue: question.groupValue,
onChanged: onChanged),
),
],
);
}
}
class Question {
final String name;
final int id;
final List<OptionModel> options;
final int groupValue;
Question(
{required this.name,
required this.id,
required this.options,
required this.groupValue});
static Question fromJson(Map<String, dynamic> json) {
return Question(
name: json['name'],
id: json['id'],
groupValue: -1,
options: (json['options'] as List)
.map((e) => OptionModel.fromJson(e))
.toList());
}
}
class OptionModel {
final String name;
final int value;
final int id;
OptionModel({required this.name, required this.id, required this.value});
static OptionModel fromJson(Map<String, dynamic> json) {
return OptionModel(
name: json['name'], id: json['id'], value: json['value']);
}
}