Consumer from Flutter provider package not updating - flutter

I have a Product listing where their is a heart icon button to mark it as favorite. using provider I am able to update the data but for the below case its not working directly.
Consumer<ProductProvider>(
builder: (ctx, product, child) => IconButton(
icon: Icon(
widget.product.isFavourite ? Icons.favorite : Icons.favorite_border,
color:
widget.product.isFavourite ? Colors.orange : iconColor,
),
onPressed: () => setState((){
widget.product.isFavourite = !widget.product.isFavourite;
}) ,
),
),
the above code is in my product card widget which is been used in Future Builder > List View builder.
if I click on the heard Icon in that list view and then navigate to that product details page. the Data is updated or that product is show to be favorite which is correct.
Now the Issue, From my Product Details Page if I click on the Heart Icon to mark that product as favorite or not favorite ( if already favorite ), then the data is updated on that page, but not in the List View Builder from previous page where the Product Card have the Consumer been used, unless the page is rebuild or I scroll the list view where more or other products are loaded which make the data update and then that change is reflected.
My product model is as below,
class ProductModel with ChangeNotifier {
...
// change product favorite status.
void toggleIsFavourite() {
this.isFavourite = !this.isFavourite;
notifyListeners();
}
}
// product details page heart button code
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 10.0),
child: IconButton(
icon : Icon(
product.isFavourite ? Icons.favorite : Icons.favorite_border,
color:
product.isFavourite ? red : iconColor,
),
onPressed: () => setState((){
product.toggleIsFavourite();
}),
),
),
],
Test Case
1) I Click on heart icon in product card and not inside heart icon on product details page.
result : Everything is working.
2) I Click on heart icon in product detail page and not inside heart icon on product card widget which is on home page.
result : heart on product card on home page is not updated unless the data of the list view is refreshed or the home page is rebuild even though I am using Consumer to just update the value for that heart icon in product card.

if you set the correct notifier above these screen, try
Consumer<ProductProvider>(
builder: (ctx, product, child) => IconButton(
icon: Icon(
product.isFavourite ? Icons.favorite : Icons.favorite_border,
color:
product.isFavourite ? Colors.orange : iconColor,
),
onPressed: () =>
product.toggleIsFavourite(),
),
),
this way your icon gets updated based on your product provider notifications.
Make sure you can access the isFavourite property of your ProductModel.
same way with product details
actions: <Widget>[
Consumer<ProductProvider>(
builder: (ctx, product, child) => Padding(
padding: const EdgeInsets.only(right: 10.0),
child: IconButton(
icon : Icon(
product.isFavourite ? Icons.favorite : Icons.favorite_border,
color: product.isFavourite ? red : iconColor,
),
onPressed: () => product.toggleIsFavourite(),
),
),
),
],
and you avoid changing widgets' states altogether.
this may not be 100% correct, but it has worked for me

Related

How can I change an Icon in flutter when i add a new Entry in my Database?

So i set up a working Realtime Database, to which i can add entries. Now i want to notify the user whenever a new entry was added to the Database by adding a little Red Dot to the Icon in the BottomNavigationBar which disappears again when the user has clicked it. Any ideas on how to achieve this?
I recommend using the badge package to achieve this. You will have to ensure the state updates using your own state management. If the user goes to the notification screen, you will need to trigger an update to mark notifications as read.
return Badge(
showBadge: unreadNotifications > 0,
badgeContent: Text(
'$unreadNotifications',
style: kTextStyle,
),
position: const BadgePosition(
top: -3,
end: 3,
),
child: IconButton(
icon: const Icon(
Icons.notifications,
),
onPressed: () {
Navigator.pushNamed(context, NotificationScreen.id);
},
),
);

Searching for the name of a specific menu - Flutter

So I'm searching for a Menu often found in a Settings Screen. It's used to select a Setting.
It opens when you press on a ListTile and then it fills the mayority of the Screen, while the borders are transparent. In the menu you have to select one of the options.
An example usecase of that would be to select a Language(onTap of the ListTile opens a Menu where you can select between all the avaliable languages)
It is similar to that of a PopupMenuButton, however as already mentioned it fills most of the screen, and the individual selectable items have a radiobutton in front of the text(probably RadioListTiles)
I hope someone gets what I'm talking about, because for the past 3 hours I'm searching for this widget but just find articles about the PopupMenuButton over and over.
Edit: I finally found an app that uses the feature I'm looking for
: https://imgur.com/a/A9k71io
By clicking on the first ListTile in the first Picture, the dialog in the second picture opens up.
Hopefully this custom widget is something roughly what you want, try to copy and paste it in your project and play with it.
this is made using the Dialog widget, to exit the Dialog you can tap out of it/ press the device back arrow and I added a small back icon on the top left corner.
tell me if it helped :)
class TestPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;// the device size
return Scaffold(
body: Center(
child: ListTile(
tileColor: Colors.grey[300],
title: Text(
'Language',
style: TextStyle(fontSize: 25),
),
onTap: () => showDialog(
context: context,
builder: (context) => Dialog(
insetPadding: EdgeInsets.all(20),
child: Container(
color: Colors.white,
height: deviceSize.height,
width: deviceSize.width,
child: Column(
children: [
Row(
children: [
IconButton(
color: Colors.red,
icon: Icon(Icons.arrow_back),
onPressed: () => Navigator.of(context).pop(),
),
],
),
Spacer(),
Text('Pick A Language'),
Spacer(),
],
),
),
),
),
),
),
);
}
}

How to update AppBar icon notification(State) from event implemented in different class?

My requirement is something like this:
Flutter - change appbar icon when receiving notification
But AppBar 'cart icon' which is to be notified on 'addToCart' button click implemented in another dart file. Am I doing something wrong by placing the AppBar and the rest in two different dart files? Let me know how to proceed.
You can use a global ValueNotifier variable. Then you can change it's content regardless the page in which you are.
Assuming this variable declaration ValueNotifier cartCounterNotifier = ValueNotifier(0);, you can update your AppBar action like this
appBar: AppBar(
// title and other
actions: [
ValueListenableBuilder(
valueListenable: cartCounterNotifier,
builder: (context, cartCounter, child) {
return Stack(
children: [
IconButton(
icon: Icon(Icons.shopping_cart_rounded),
onPressed: () {},
),
Positioned(
child: 0 < cartCounter ? Container(
decoration: ShapeDecoration(
color: Colors.red,
shape: CircleBorder(),
),
padding: EdgeInsets.all(2.0),
child: Text("$cartCounter", style: TextStyle(
color: Colors.white,
),),
) : SizedBox(),
),
],
);
}
)
],
),
Update:
So to update your action button, simply change the content of your variable like this
cartCounterNotifier.value = cartCounterNotifier.value + 1; // or another value

Appbar widgets not refreshing instantly on calling setState() Flutter

The AppBar of my app has the cart widget which uses a badge for showing the number of items in the cart.
When I place the exact same cart in my body of the Scaffold, it updates the state instantly on adding or removing items from the cart. But in my appbar, the cart widget's state doesn't get updated. It's very weird.
actions: <Widget>[
Badge(
badgeContent: Text('${selectedItems.length}',
style: TextStyle(color: Colors.white)),
position: BadgePosition.topRight(top: 0.0, right: 5.0),
badgeColor: Colors.black,
showBadge: selectedItems.length == 0 ? false : true,
child: IconButton(
icon: Icon(Icons.shopping_cart),
onPressed: () => Navigator.push(context,
CupertinoPageRoute(builder: (context) => CartScreen())),
color: Colors.black,
),
)
],
As you can see, the selectedItems.length is the number of items in my cart.
Please help me out. Stuck here for a long time now...

Dynamically added widget works only after route change

I am using the flutter Slidable widget inside a SliverList, where the list elements are pulled from an array. I use setState to update the list.
The problem I am having is that after the list update, I can see all new elements correctly, but the slidable functionality doesn't work. However, after entering a new page with push and leaving with pop, the slidable functionality starts working.
Why is this happening?
return SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => Card(
child: InkWell(
child: Slidable(
key: Key(_fileList[index].key),
actionPane: SlidableDrawerActionPane(),
child: Container(
child: ListTile(
onTap: () {
...
},
title: Text(_fileList[index].subtitle),
subtitle: Text(_fileList[index].subtitle),
),
),
secondaryActions: <Widget>[
IconSlideAction(
caption: 'Delete',
color: Colors.red,
icon: Icons.delete,
onTap: () {
...
}
),
],
),
),
),
childCount: _fileList.length,
),
);
Updating is done like this:
setState(() {
_fileList = newFileList;
});
i think you may try not to test on hot reload
just type in terminal : flutter run
Never mind, i accidentally disabled and then re-enabled the SlidableController.