Home > database >  Pass function with parameter to child. Parameter should come from child
Pass function with parameter to child. Parameter should come from child

Time:03-15

Imagine I have a parent widget and a child widget. In the parent widget, there is a variable: 'page index'. And the child widget needs to change that variable in a set state method (because it has to be refreshed). How can I do this?

The body of the scaffold renders content based on the pageindex.

The code

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int pageIndex = 0;
  List<Widget> pageList = <Widget>[
    HomeScreen(),
    ProfileScreen(),
    CartScreen(),
    ProfileScreen(),
    ProfileScreen()
  ];
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => CartViewModel()),
      ],
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Home page',
        theme: theme(),
        onGenerateRoute: generateRoute,
        home: Scaffold(
          bottomNavigationBar: BottomNavBar(pageIndex, setPageIndex()),
          body: pageList[pageIndex],
        ),
      ),
    );
  }

  void setPageIndex(newValue) {
    setState(() {
      pageIndex = newValue;
    });
  }
}

class BottomNavBar extends StatefulWidget {
  BottomNavBar(this.pageIndex, this.setPageIndexFunction);
  int pageIndex;
  VoidCallback setPageIndexFunction;
  @override
  State<BottomNavBar> createState() => _BottomNavBarState();
}

class _BottomNavBarState extends State<BottomNavBar> {
  @override
  Widget build(BuildContext context) {
    CartViewModel cartViewModel = context.watch<CartViewModel>();

    return BottomNavigationBar(
      elevation: 5,
      backgroundColor: Colors.white,
      currentIndex: widget.pageIndex,
      type: BottomNavigationBarType.fixed,
      fixedColor: kAccentColor,
      items: [
        const BottomNavigationBarItem(
            label: "Home", icon: Icon(Icons.home_outlined)),
        const BottomNavigationBarItem(
            label: "Search", icon: Icon(Icons.search_outlined)),
        BottomNavigationBarItem(
            label: "Cart",
            icon: buildCustomBadge(
              counter: cartViewModel.loading == false
                  ? cartViewModel.cart!.count
                  : 0,
              child: Icon(Icons.shopping_bag_outlined),
            )),
        const BottomNavigationBarItem(
            label: "Favorite",
            icon: Icon(Icons.favorite_border_outlined)),
        const BottomNavigationBarItem(
            label: "Profile", icon: Icon(Icons.person_outline))
      ],
      onTap: (value) {
        widget.setPageIndexFunction(value);
      },
    );
  }
}

What is the problem

I am trying to call the function: "setPageIndexFunction(value)" and pass in the clicked value. Then it should call the function "setState" in the parent.

How can I do this? The reason I put the bottomnavbar in a separate widget is because I could not write this line of code in the MyApp class: "CartViewModel cartViewModel = context.watch();". I need this line to check if an item has been added to my cart and show it in the bottomnavbar.

Or should I use provider for this?

Thanks!

CodePudding user response:

Try these steps:

  1. Use ValueChanged<int> instead of VoidCallback
class BottomNavBar extends StatefulWidget {
  BottomNavBar(this.pageIndex, this.setPageIndexFunction);
  int pageIndex;
  ValueChanged<int> setPageIndexFunction;
  @override
  State<BottomNavBar> createState() => _BottomNavBarState();
}
  1. Use setPageIndex in _MyAppState as a tear-off.
  bottomNavigationBar: BottomNavBar(pageIndex, setPageIndex),
  • Related