So I am trying to add filters to my calorie tracking app and I encountered this problem. I try to individually change the value of different booleans (ex.: vegan, keto ...) and it changes in the widget that I change them in (Item), but not in the parent (CategoryGrid) widget. Although, the value of _isSelected changes as it is supposed to, the value of categoryType is not reflected in the parent (CategoryGrid) widget. This is the code:
class CategoryGrid extends StatefulWidget {
Recipe recipe;
CategoryGrid(this.recipe);
@override
State<CategoryGrid> createState() => _CategoryGridState();
}
class _CategoryGridState extends State<CategoryGrid> {
bool isVegan = false;
bool isVegetarian = false;
bool isKeto = false;
bool isLowFat = false;
bool isLowCarbs = false;
bool isLowCalories = false;
@override
void setState(VoidCallback fn) {
isVegan = widget.recipe.isVegan;
isVegetarian = widget.recipe.isVegetarian;
isKeto = widget.recipe.isKeto;
isLowFat = widget.recipe.isLowFat;
isLowCarbs = widget.recipe.isLowCarbs;
isLowCalories = widget.recipe.isLowCalories;
super.setState(fn);
}
void changeValue(bool value) {
setState(() {
value = !value;
});
print(value);
}
@override
Widget build(BuildContext context) {
return Container(
...
Item('Vegan', isVegan, changeValue),
Item('Vegetarian', isVegetarian, changeValue),
Item('Low-fat', isLowFat, changeValue),
Item('Low-carbs', isLowCarbs, changeValue),
Item('Low-calories', isLowCalories, changeValue),
Item('Keto', isKeto, changeValue),
...
),
ElevatedButton(
...
onPressed: () {
widget.recipe = Recipe(
id: widget.recipe.id,
title: widget.recipe.title,
ingredients: widget.recipe.ingredients,
steps: widget.recipe.steps,
servings: widget.recipe.servings,
description: widget.recipe.id,
creatorId: widget.recipe.id,
p: widget.recipe.p,
c: widget.recipe.c,
f: widget.recipe.f,
kcal: widget.recipe.kcal,
imageUrl: widget.recipe.imageUrl,
isVegan: isVegan,
isKeto: isKeto,
isLowCalories: isLowCalories,
isLowCarbs: isLowCarbs,
isLowFat: isLowFat,
isVegetarian: isVegetarian,
);
print(widget.recipe.isKeto);
print(widget.recipe.isVegan);
Navigator.of(context).pop(widget.recipe);
},
child: const Text('Save filters'),
...
}
}
// The individual item widget
class Item extends StatefulWidget {
final String data;
bool categoryType;
Function changeValue;
Item(this.data, this.categoryType, this.changeValue);
@override
State<Item> createState() => _ItemState();
}
class _ItemState extends State<Item> {
bool _isSelected = false;
@override
Widget build(BuildContext context) {
return ElevatedButton.icon(
...
onPressed: () {
setState(() {
_isSelected = !_isSelected;
widget.categoryType = _isSelected;
});
widget.changeValue(widget.categoryType);
},
...
);
}
}
CodePudding user response:
In your case it was not working because, In below method you are updating the value to true/false
onPressed: () {
setState(() {
_isSelected = !_isSelected;
widget.categoryType = _isSelected;
});
widget.changeValue(widget.categoryType);
},
And in below method you are again updating it
void changeValue(bool value) {
setState(() {
value = !value;
});
print(value);
}
So you have two choice, 1. Stop updating value in child 2. Stop updating value in parent. I believe you should stop updating value in child and remove _isSelected variable from item widget.
class Item extends StatefulWidget {
final String data;
bool categoryType;
Function changeValue;
Item(this.data, this.categoryType, this.changeValue);
@override
State<Item> createState() => _ItemState();
}
class _ItemState extends State<Item> {
@override
Widget build(BuildContext context) {
return ElevatedButton.icon(
/// Use the widget.categoryType to make this button selected.
...
onPressed: () {
widget.changeValue(widget.categoryType);
},
...
);
}
}
CodePudding user response:
There are two changes that you have to do:
- In your
changeValue
function you are updating the value of function parametervalue
, not your bool variables likeisVegan
,isVegetarian
, etc - You are passing isVegan, isVegetarian value to your
Item
widget. Anyway the value which you are setting tocategoryType
in your Item widget will not update the parent variables because dart does not have reference parameters. Arguments are passed as values.
You have to set the value
to your isVegan, isVegetarian, ... variables by passing a separate function callback like this.
Item('Vegan', isVegan, (value) {isVegan = value; }),
Item('Vegetarian', isVegetarian, (value) {isVegetarian = value; }),
... // so on for all your items