getx icon indicating copy to clipboard operation
getx copied to clipboard

Cache results in example_nav2

Open steven-spiel opened this issue 3 years ago • 8 comments

There is a common use case for tabs to hold their state when switching among them. In the example_nav2, when selecting a product, it redirects to the product details, but then when visiting another tab and returning to the products tab, the product details are not longer visible.

https://user-images.githubusercontent.com/77690617/128570427-3d917996-38fb-43ed-b938-263b47dbfecf.mov

Is there a simple solution to this?

I'm considering specifying different GetDelegates for each tab and using Offstage widgets to hide inactive tabs, but I imagine there is an easier way. And if the plugin were to solve the problem, how would you go about doing it?

steven-spiel avatar Aug 06 '21 21:08 steven-spiel

@ahmednfwela do you have any thoughts on how this can be accomplished?

steven-spiel avatar Aug 07 '21 20:08 steven-spiel

I kind of got it working by doing this:

https://user-images.githubusercontent.com/77690617/128708558-e15d0c7e-e7e5-441d-8808-0d0e9171345f.mov

class HomeController extends GetxController {
  final RxInt tabIndex = 0.obs;
}

class HomeView extends GetView<HomeController> {
  @override
  Widget build(BuildContext context) {
    return GetRouterOutlet.builder(
      builder: (context, delegate, currentRoute) {
        return Obx(() {
          return Scaffold(
            body: Stack(
              children: [
                Offstage(
                  offstage: controller.tabIndex() != 0,
                  child: GetRouterOutlet(
                    initialRoute: Routes.DASHBOARD,
                    anchorRoute: Routes.DASHBOARD,
                    key: Get.nestedKey(Routes.HOME),
                  ),
                ),
                Offstage(
                  offstage: controller.tabIndex() != 1,
                  child: GetRouterOutlet(
                    initialRoute: Routes.PROFILE,
                    anchorRoute: Routes.PROFILE,
                    key: Get.nestedKey(Routes.PROFILE),
                  ),
                ),
                Offstage(
                  offstage: controller.tabIndex() != 2,
                  child: GetRouterOutlet(
                    initialRoute: Routes.PRODUCTS,
                    anchorRoute: Routes.PRODUCTS,
                    key: Get.nestedKey(Routes.PRODUCTS),
                  ),
                ),
              ],
            ),
            bottomNavigationBar: BottomNavigationBar(
              currentIndex: controller.tabIndex(),
              onTap: (value) {
                switch (value) {
                  case 0:
                    if (controller.tabIndex() == 0) {
                      delegate.backUntil(Routes.HOME);
                    } else {
                      controller.tabIndex.value = 0;
                    }
                    break;
                  case 1:
                    if (controller.tabIndex() == 1) {
                      delegate.backUntil(Routes.PROFILE);
                    } else {
                      controller.tabIndex.value = 1;
                    }
                    break;
                  case 2:
                    if (controller.tabIndex() == 2) {
                      delegate.backUntil(Routes.PRODUCTS);
                    } else {
                      controller.tabIndex.value = 2;
                    }
                    break;
                  default:
                }
              },
              items: [
                // _Paths.HOME + [Empty]
                BottomNavigationBarItem(
                  icon: Icon(Icons.home),
                  label: 'Home',
                ),
                // _Paths.HOME + Routes.PROFILE
                BottomNavigationBarItem(
                  icon: Icon(Icons.account_box_rounded),
                  label: 'Profile',
                ),
                // _Paths.HOME + _Paths.PRODUCTS
                BottomNavigationBarItem(
                  icon: Icon(Icons.account_box_rounded),
                  label: 'Products',
                ),
              ],
            ),
          );
        });
      },
    );
  }
}

The primary issue is that the nav stack doesn't get updated when switching tabs (I'm still not sure how to update the history without forcing a reload, though I bet there is a way)

steven-spiel avatar Aug 09 '21 12:08 steven-spiel

Do you see any glaring issues with this approach? Is this something worth baking into a GetBottomTabView?

steven-spiel avatar Aug 09 '21 12:08 steven-spiel

The other issue I'm observing is that navigating to a new route on one tab will reset all other tabs back to their anchorRoutes

steven-spiel avatar Aug 09 '21 14:08 steven-spiel

Actually the solution is much simpler than this, change the onTap logic here https://github.com/jonataslaw/getx/blob/master/example_nav2/lib/app/modules/home/views/home_view.dart#L37 to this:

case 2:
  final nearestEntryIndex = delegate.history.lastIndexWhere(
    (entry) =>
        entry.location?.startsWith(Routes.PRODUCTS) == true,
  );
  final nearestEntry = nearestEntryIndex >= 0
      ? delegate.history[nearestEntryIndex].location!
      : Routes.PRODUCTS;
  delegate.toNamed(nearestEntry);
  break;

ahmednfwela avatar Aug 09 '21 18:08 ahmednfwela

Hi, Any news about keeping states for bottom nav bar pages? Im also facing with same issue.

@ahmednfwela Is there any easy way?

gorkemsari avatar Sep 24 '21 09:09 gorkemsari

Get.put<MyController>(MyController(), permanent: true);

permanent=true solved my problem.

gorkemsari avatar Sep 24 '21 12:09 gorkemsari

I'm also using version 4.6.5 and have the same problem. It seems that this problem has always existed and has not been solved yet

wilhantian avatar Sep 11 '22 03:09 wilhantian