i have problem with GetMidleware
, so i have 3 item in bottomNavigationBar
:
i want user can acces home without login so i put midleware just on myTicket
and Profile
, but when i click MyTicket or Profile i still can access that and not redirect to login page.
this is my midleware class :
class AuthMiddleware extends GetMiddleware {
final authService = Get.find<AuthService>();
@override
RouteSettings? redirect(String? route) {
if (!authService.currentUser.value.isAuthenticated) {
Get.log(authService.currentUser.value.isAuthenticated.toString());
return const RouteSettings(name: Routes.LOGIN);
}
return null;
}
}
this is my appPage class :
class AppPages {
static const INITIAL = Routes.ROOT;
static final routes = [
GetPage(
name: _Paths.ROOT,
page: () => const RootView(),
binding: RootBinding(),
),
GetPage(
name: _Paths.HOME,
page: () => const HomeView(),
binding: RootBinding(),
),
GetPage(
name: _Paths.MYTICKET,
page: () => const MyTicketView(),
binding: RootBinding(),
middlewares: [AuthMiddleware()],
),
GetPage(
name: _Paths.PROFILE,
page: () => const ProfileEditView(),
binding: RootBinding(),
middlewares: [AuthMiddleware()],
),
]
}
this is my root controller:
class RootController extends GetxController {
final Rx<String> title = Strings.home.obs;
final Rx<int> currentIndex = 0.obs;
final authService = Get.find<AuthService>();
@override
void onClose() {
super.dispose();
}
List<Widget> pages = [
const HomeView(),
const MyTicketView(),
const ProfileView(),
// const BlankView(),
];
//get current page for view
Widget get currentPage => pages[currentIndex.value];
//change page when bottom nav item is taped
Future<void> changePage(int _index) async {
changeTitle(_index);
if (Get.currentRoute == Routes.ROOT) {
await changePageInRoot(_index);
} else {
await changePageOutRoot(_index);
}
}
Future changeTitle(int index) async {
switch (index) {
case 0:
title.value = Strings.home;
break;
case 1:
title.value = Strings.myTicket;
break;
case 2:
title.value = Strings.myProfile;
break;
default:
}
}
//change page if previously page in root
Future<void> changePageInRoot(int _index) async {
currentIndex.value = _index;
await refreshPage(_index);
}
//change page if previously page out of root
Future<void> changePageOutRoot(int _index) async {
currentIndex.value = _index;
await refreshPage(_index);
await Get.offNamedUntil(Routes.ROOT, (Route route) {
if (route.settings.name == Routes.ROOT) {
return true;
}
return false;
}, arguments: _index);
}
}
//call page by index
Future<void> refreshPage(int _index) async {
switch (_index) {
case 0:
{
Get.find<HomeController>().onInit();
break;
}
case 1:
{
Get.find<MyTicketController>().onInit();
break;
}
case 2:
{
Get.find<ProfileController>().onInit();
// Get.find<BlankController>().onInit();
break;
}
}
}
and this is my root view where i put my bottomNavigationBar
:
class RootView extends GetView<RootController> {
const RootView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Obx(
() => Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(Dimensions.appBarHeight),
child: BackWidget(title: controller.title.value),
),
backgroundColor: Colors.white,
bottomNavigationBar: Material(
elevation: 10,
// borderRadius: BorderRadius.circular(20),
child: BottomNavigationBar(
selectedIconTheme:
const IconThemeData(color: CustomColor.primaryColor),
selectedLabelStyle: const TextStyle(fontSize: 15),
selectedItemColor: CustomColor.primaryColor,
backgroundColor: Colors.white,
elevation: 25,
type: BottomNavigationBarType.fixed,
currentIndex: controller.currentIndex.value,
onTap: (index) => controller.changePage(index),
items: [
bottomNavigationBarItemWidget(
'assets/svg/home.svg',
Strings.home,
),
bottomNavigationBarItemWidget(
'assets/svg/document.svg',
Strings.myTicket,
),
bottomNavigationBarItemWidget(
'assets/svg/profile.svg',
Strings.myProfile,
),
]),
),
body: controller.currentPage,
),
);
}
bottomNavigationBarItemWidget(String icon, String label) {
return BottomNavigationBarItem(
icon: SvgPicture.asset(
icon,
color: Colors.grey,
height: 24,
width: 24,
),
activeIcon: SvgPicture.asset(
icon,
color: CustomColor.primaryColor,
height: 24,
width: 24,
),
label: label,
tooltip: label,
);
}
}
BottomNavigationBar (also TabBar) doesn't change routes. It's essentially single page. Therefore route middlewares can't be used with them without complications.
Instead, you can use the auth check on the respective controllers of the views of navigation bar items. A very good place is in the onReady
method of the GetxController
s.