Search code examples
flutterdartflutter-dependencies

How to dynamically update badge count on Badge in NavigationBar?


I have the following navigation bar in my flutter app:

BottomNavigationBar(
  items: [
    const BottomNavigationBarItem(
      icon: Icon(Icons.home),
      label: 'Home',
    ),
    BottomNavigationBarItem(
      icon: appState.itemCard.cardItems.isNotEmpty   // only show Badge when items are cardItems
          ? badges.Badge(                            // This is the Badge
              badgeContent: Text(appState
                  .itemCard.cardItems.values
                  .reduce((a, b) => a + b)
                  .toString()),
              child: const Icon(Icons.shopping_cart),
            )
          : const Icon(Icons.shopping_cart),
      label: 'Card',
    ),
    const BottomNavigationBarItem(
      icon: Icon(Icons.menu),
      label: 'Menu',
    ),
  ],
  currentIndex: selectedIndex,
  onTap: (value) {
    setState(() {
      selectedIndex = value;
    });
  },
)

The issue is that when I make changes to the itemCard.cardItems the badge count doesn't update until I click on another NavigationBarItem like Home.
How can I achieve that the badge updates immediately when I add items to the itemCard.cardItems?

Edit - Solution, thank you @Abhishek Karad

I've created a ValueNotifier for the value in the ItemCard Class:

class ItemCard {
  Map<Item, int> cardItems = {};
  double totalPrice = 0.0;
  ValueNotifier<int> totalItems = ValueNotifier<int>(0); // <-- this one
}

In the next step I wrapped the icon of the corresponding BottomNavigationBarItem with the ValueListenableBuilder:

BottomNavigationBarItem(
  icon: ValueListenableBuilder( // wrapped Icon
      builder: (context, value, child) => badges.Badge(
            showBadge:
                appState.itemCard.totalItems.value > 0,
            badgeContent: Text(appState
                .itemCard.totalItems.value
                .toString()),
            child: const Icon(Icons.shopping_cart),
          ),
      valueListenable: appState.itemCard.totalItems), // ValueNotifier
  label: 'Card',
),

Solution

  • Suppose you have

    List<CartModel> appState.itemCard.cardItems =[]
    

    in your AppState file

    Replace it to

    ValueNotifier<List<CartModel>> appState.itemCard.cardItems =ValueNotifier<List<CartModel>>([]);
    

    And replace

    BottomNavigationBarItem(
          icon: appState.itemCard.cardItems.isNotEmpty   // only show Badge when items are cardItems
              ? badges.Badge(                            // This is the Badge
                  badgeContent: Text(appState
                      .itemCard.cardItems.values
                      .reduce((a, b) => a + b)
                      .toString()),
                  child: const Icon(Icons.shopping_cart),
                )
              : const Icon(Icons.shopping_cart),
          label: 'Card',
        ),
    

    to

    ValueListenableBuilder(builder : (BuildContext context, int value, Widget? child) {
                // This builder will only get called when the _counter
                // is updated.
                return Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: <Widget>[
                    Text('$value'),
                    child!,
                  ],
                );},valueListenable: appState
                      .itemCard.cardItems)
    

    if you are already using ValueNotifier then just wrap your widget with ValueListenableBuilder

    For More https://api.flutter.dev/flutter/widgets/ValueListenableBuilder-class.html