I’m trying to build a shopping list based on meals ingredients that are passed in Route Settings on which user can select/deselect each items separately. Here is the code:
import 'package:cookup/src/consts/colors.dart';
import 'package:flutter/material.dart';
import '/dummy_data.dart';
class ShoppingListScreen extends StatefulWidget {
static const routeName = '/shoppig-list';
final Function toggleFavorite;
final Function isFavorite;
ShoppingListScreen(this.toggleFavorite, this.isFavorite);
@override
State<ShoppingListScreen> createState() => _ShoppingListScreenState();
}
class _ShoppingListScreenState extends State<ShoppingListScreen> {
bool isSelected = false;
@override
Widget build(BuildContext context) {
final mealId = ModalRoute.of(context)?.settings.arguments as String;
final selectedMeal = DUMMY_MEALS.firstWhere((meal) => meal.id == mealId);
return Scaffold(
appBar: AppBar(
iconTheme: IconThemeData(color: kFontColorBlack),
backgroundColor: kBackgroundColor,
title: Text(
'${selectedMeal.title}',
maxLines: 2,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
style: TextStyle(color: kFontColorBlack),
),
actions: [
IconButton(
icon: Icon(
widget.isFavorite(mealId)
? Icons.favorite
: Icons.favorite_border,
),
onPressed: () => widget.toggleFavorite(mealId),
),
],
),
body: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
height: 250,
width: double.infinity,
child: Image.network(
selectedMeal.imageUrl,
fit: BoxFit.cover,
),
),
Container(
alignment: Alignment.topLeft,
margin: EdgeInsets.symmetric(vertical: 10),
child: const Padding(
padding: EdgeInsets.all(16.0),
child: Text(
"Ingredients",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 22.0,
),
),
),
),
ListView.builder(
itemCount: selectedMeal.ingredients.length,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return CheckboxListTile(
title: Text(selectedMeal.ingredients[index]),
value: isSelected,
controlAffinity: ListTileControlAffinity.leading,
onChanged: (
value,
) {
setState(() {
isSelected = value!;
});
},
);
},
),
],
),
),
);
}
}
and the result is visible here as I got stuck having all items being selcted/deselected on click:
enter image description here
Which is not the expeted behaviour as I need only one item being seletced on click. I was trying variious things but end up having either the above result, having some error regaridng incorrect list Range or I got error that dependOnInheritedWidgetOfExactType<_ModalScopeStatus>() or dependOnInheritedElement() was called before _ShoppingListScreenState.initState() completed
. What I am doing wrong? Please help! 🙂
2
Answers
Thanks! I have updated the model from the list to a map with a boolean value and used below builder code - it works as expected now:
The reason why you are getting this error is you are passing the same value
isSelected in all your items in the ListView.builder.
You have to add a boolean field in your model class which will store the value for each and every item in your list.
Consider following example for model class.
Hope this helps !