Reputation: 317
I am using the go router plugin for my flutter web application, but I didn't find any way to do push replacement in navigation.
not only push replacement, can we do any other type of navigation link
What I tried
they only pushed the next page, not replacing
Note: I want this functionality in go router
Upvotes: 13
Views: 27080
Reputation: 312
You can separately use route functions, for example if you want to use pushNamedAndRemoveUntil, you can try it adding by onExit
function inside of your router.
I tried this:
final GoRouter _router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => Container(),
),
GoRoute(
path: '/admin',
builder: (context, state) => const Login(),
),
GoRoute(
path: '/admin/home',
onExit: (_) => false, <--- Added this line. This just terminate the operation
builder: (context, state) => const Home(),
),
],
);
and so on. There are another functions available to use. The same with redirect
. There is redirect
argument function in GoRouter
class. you can try it one by one
Upvotes: 0
Reputation: 17291
Here's a workaround that I did. I created an extension
to BuildContext
.
extension GoRouterContextX on BuildContext {
void _doPop<T extends Object?>([T? result]) {
if (Navigator.of(this).canPop()) {
pop(result);
}
}
/// Pop repeatedly until the specified location.
///
/// If non-null, `result` will be used as the returned result.
void popUntil<T extends Object?>(String location, [T? result]) {
final routeInfo = GoRouter.of(this).routeInformationProvider;
final routeMatches =
(routeInfo.value.state as Map?)?['imperativeMatches'] as List<Map>;
final routeLocations = routeMatches
.map<String>((e) => e['location'])
.toList()
.reversed
.toList();
if (routeLocations.isEmpty) {
_doPop<T>(result);
}
for (var routeLoc in routeLocations) {
if (routeLoc != location) {
_doPop<T>(result);
} else {
break;
}
}
}
}
Use it like this:
context.popUntil(route_path_here, true);
Note:
At the time of this answer, I am using:
- GoRouter 12.0.1
- Flutter 3.13.9
- Dart 3.1.5
Upvotes: 0
Reputation: 31
This is what I found from doc:
context.replace(location)
Replaces the top-most page of the page stack with the given one but treats it as the same page. The page key will be reused. This will preserve the state and not run any page animation.
Upvotes: 2
Reputation: 720
If you are using a nested or ShellRoute and want to avoid browser history to record the unnecessery navigation actions consider using neglect
onTap(){
Router.neglect(context, () => context.go('/profile/security'));
}
Upvotes: 0
Reputation: 101
You can use something like this;
while (context.canPop()) {
context.pop();
}
context.pushReplacement(path, extra: data);
Upvotes: 4
Reputation: 24940
In the latest go_router
, You can use
context.pushReplacement('/login');
void pushReplacement(
String location,
{Object? extra}
)
context.pushReplacementName(Routes.login)
(Routes is a class having defination of login)void pushReplacementNamed(
String name,
{Map<String, String> params = const <String, String>{},
Map<String, dynamic> queryParams = const <String, dynamic>{},
Object? extra}
)
Upvotes: 10
Reputation: 65
Edited
i use this functions and they are useful for me
void popUntil(String name){
GoRouter router= AppRoutes.router;
String currentRoute=router.location;
while(router.canPop()&&name!=currentRoute){
currentRoute=router.location;
if(name!=currentRoute){
router.pop();
}
}
}
void pushNamedAndRemoveUntil(String name){
GoRouter router= AppRoutes.router;
while(router.canPop()){
router.pop();
}
router.replaceNamed(name);
}
work same as pushNamedAndRemoveUntil(route_name, (Route<dynamic> route) => false);
any suggestion please drop a comment
Upvotes: 0
Reputation: 8192
In the current version of go_router
(5.1.10
), you can use GoRouter.of(context).replace('/your-route)
to do the same as Navigator.of(context).pushReplacement(yourPage)
.
There is a PR open to add popUntil
but it looks like the flutter team doesn't want to support imperative routing methods and only focus on declarative routing (see, this issue).
It means the popUntil
PR might never be merged, and pushNamedAndRemoveUntil
never be supported.
It also means that push
and replace
might be removed in the future.
Upvotes: 1
Reputation: 19
I have had the same problem before. Then this way worked for me First you need to avoid nested routes:
final GoRouter router = GoRouter(
routes: <GoRoute>[
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) =>
const OnboardingScreen(),
),
GoRoute(
path: '/login',
builder: (BuildContext context, GoRouterState state) => LoginScreen(),
),
GoRoute(
path: '/signup',
builder: (BuildContext context, GoRouterState state) =>
const SignupScreen(),
),
],
);
Use the above code instead of nesting like this:
final GoRouter router = GoRouter(
routes: <GoRoute>[
GoRoute(
routes: <GoRoute>[
GoRoute(
path: 'login',
builder: (BuildContext context, GoRouterState state) => LoginScreen(),
),
GoRoute(
path: '/signup',
builder: (BuildContext context, GoRouterState state) =>
const SignupScreen(),
),
],
path: '/',
builder: (BuildContext context, GoRouterState state) =>
const OnboardingScreen(),
),
],
);
This will make you able to replace OnboardingScreen() from the above eg. So next you can use pushreplacement future with:
context.go("/routname");
or GoRouter.of(context).go("/routname"); If u don't want replacement, then can just use:
context.push("/routname");
or
GoRouter.of(context).push("/routname");
Upvotes: 1
Reputation: 106
What you can do is use Sub-Route Redirects in Go Router.
Let's consider you want users to first go on your Homepage and then from there they tap Login, and go to Login page and then after Logging in, they go to Dashboard Page.
But when they press Browser's Back Button they should go to Homepage and not the LoginPage i.e skipping the LoginPage just like "pushNameReplacement".
Then for this to happen you can configure redirects of each LoginPage and Dashboard page and get this functionality.
You can configure it such that whenever user (including from Browser's History) goes to Dashboard link it first checks if its Logged In then it opens otherwise it displays Login Page automatically.
Upvotes: 0
Reputation: 478
You can do it in a way ->
context.pop();
context.push(routeName);
Adding both these commands works similar to pushReplacement.
Upvotes: 3
Reputation: 568
Try this
Router.neglect(context, () {
context
.goNamed('third', params: {"id": ID});
});
It will neglect your current page. Hop this will helps you
Upvotes: 6