You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Since the design doc mentioned nested Navigators, I wonder whether routing could be something extensible, where Navigator aren't the only widgets representing part of the route. For example:
In our apps, we have a Navigator at the root (the one in WidgetsApp) that we use to navigate between onboarding and daily UI. In Daily UI we have a (custom build) tab bar. Each tab has a Navigator for navigation within the tab (we want each tab to have an independent stack of pages). For one of the inner Navigators (the one showing settings), we'd like to show a different design on large devices, where the first page is shown on the left of the screen and used to select a page on the right side of the screen (a master-detail view, like the iOS Settings app).
To handle deep links, it would be useful if routing could incorporate widgets like a tab bar or a master-detail view.
Reacted by CDDelta, Jonas Wanke, Allan, Christian Mürtz, Jason C.H, Ayoosh Agarwal, Miguel Medeiros, Yura Stetsyk, Christopher Boyd, Tom Alabaster and 1 more
@chunhtai What about custom navigation to widgets similar to Fragments in Android?
For example if I have a Form screen with several steps and I want to use navigation between Tabs is it possible I can use Navigator 2.0 but for Tabs?
@amreniouinnovent I am not entirely sure what effect you would like to achieve. I imagine you should be able to achieve most by writing custom url parser with custom page, and on onPopPage.
Can you explain more details on how would you expect to use the api, and what is the effect?
In my Navigation Bloc Fragment, I have the same page but I switch between Sub widgets by my Bloc.
Drawer and AppBar are fixed while widgets are changed.
@MajedDH I checked the example it is very good
However that we can achieve that in different ways but not the same as fragments in Android.
What if you want that in a Dialog you will have to add unnecessary complexity for just a simple task.
Android fragments are an awesome and simple way of nested navigation.
I think for now my bloc is good enough but it would be awesome if I could see fragments in Flutter
@amreniouinnovent That will likely to be a new widget that wraps the navigator to provide more convenient api. I think that should separate from this issue, feel free to file a new feature request
I agree with @royibernthal that currently (and it'll get worse with Navigator 2.0), showing overlays in response to an InheritedWidget state change is not great.
We had some sort of solution, that is didChangeDepencencies. But it recently broke on the master channel (see #49527).
In my opinion, Navigator 2.0 should also include an Overlay 2.0 with the same reasoning than Navigator:
OverlayEntry is currently imperative, and this is bad.
So it'd be great to have a declarative Overlay manipulation instead. That's how React deals with overlays.
This would completely solve the "showing overlays in answer to an InheritedWidget change" issue, as it'd just be our typical build method doing its work.
I made an implementation of such declarative Overlay very recently actually: https://github.com/rrousselGit/flutter_portal. It's tested and most features are implemented – feel free to take a look.
It's up to the team to think about it, but I am convinced that this flutter_portal thing should not be as a package since it's literally OverlayEntry.
Also, all functions like showDialog, showSnackbar, ..., should be made declarative too, not just OverlayEntry.
If needed, I'm open to discussing with the team, make an issue, or potentially make a design doc (although I'd like to avoid the latter – too much work for me).
Reacted by Royi Bernthal, Lukasz Piliszczuk, Timur Artikov, Yaroslav Kiliba, nesscx, Bardia Rastin, mono — Masayuki Ono, Emrah Bilbay, Robert Felker, Arnaud Jezequel and 14 more
@rrousselGit I am not sure if I understand, how would Navigator 2.0 makes the overlay issue worse?
I would like to separate out the overlay entry issue from the navigator refactoring as it the navigator refactor is already pretty complicated. Would you open up a new feature request for merging the library and we can continue our discussion there?
@lukepighetti They meant different things, we separate out the browser history and navigator route stack. The browser back button means build the app with the previous url, and the back button on appbar means means pop the top most route off the route stack.
@lukepighetti
Do you mean appbar back button should work the same as browser backward button, or the browser backward button should work the same as appbar back button?
if you meant the former:
The app bar is originally built with imperative API, so we automatically shows the backbutton when there are multiple routes underneath. This mechanism makes sense for mobile application because mobile has the concept of route stack. If you don't want this behavior you can write your own declarative back button
if you meant the latter:
The previous page can be an arbitrary page, it can be a certain page in the app or a page in a completely different website. The browser backward button is used for bring user back to the previous page. It does more than just popping top most route of the app.
In a fully declarative router where a single input (ie a url string) always results in the same navigator stack shown on screen, then it seems like there should be no difference between the app back button and the browser back button. The app back button cannot mutate the stack, as the router would no longer be declarative. All it should be able to do is go back one item in the router history. It would be up to us to modify the history if we need to layer things a certain way. This is not the same thing as modifying the navigator stack because it's still 100% declarative.
TLDR the app back button should pop the last history item off the router history, just like the back button. Not mutate the underlying stack by popping a single route/page, because that breaks the promise of being fully declarative.
Reacted by Jarle Stabell, jibiel, Illia Romanenko and Rongix
In a fully declarative router where a single input (ie a url string) always results in the same navigator stack shown on screen, then it seems like there should be no difference between the app back button and the browser back button.
I think that's not desired. Imagine opening https://navigator_20_example.codemagic.app/#/details/5 and then pressing browser back button. It would be strange to be moved to details/4 or Home. Natural thing to observe would be to go back to this issue.
The AppBar button, however, is very mobile-oriented so it's relatively normal to go back to the previous page within the app i.e. Home.
Edit: one way I can think of would be to add web-oriented AppBar which would imitate the native back button behavior. Or just don't show AppBar's back button on web at all ;)
Reacted by Dimitri Leurs, Christopher Boyd and Ray Li
Nothing I've said is unique to browsers, especially since Android has a hardware back button.
The situation you describe would be resolved with a method/delegate that builds the nav history on first load, much like how the current navigator does that with /onboarding/start building a page stack and route name like this:
page stack
/
/onboarding
/onboarding/start
route name
/onboarding/start
Comparing to what I said, instead of doing pages like that, you'd do history entries. Like this:
route history
/
/onboarding
/onboarding/start
Where the android back button, web back button, or app bar back button pop the current history entry and build the declarative route stack based on the previous (now current) route.
The only time they would differ is when to hide the app bar back button. The web/android back button would eventually take you to the website/app you were on previously, once you've exhausted the Flutter route history.
Friendly ping on this. Maybe the ship has sailed, but I fear that Nav 2.0 is a declarative/imperative hybrid instead of fully declarative. It's my understanding that the core design specification called for it to be 100% declarative. I might be missing something, but I think I've given the issue an appropriate amount of care in thinking it through.
We make it a hybrid for backward compatibility, you can definitely go full declarative by customizing the behavior for android back button in routerdelegate.popRoute.
@Milad-Akarie In a fully declarative world then yes. There are still a lot of widget that relies on imperative push/pop, dialog for example, and they makes sense to stay imperative due to their functionality. In those cases, awaiting for route is still useful.
@chulwoo-park me again! if we can decide wether or not to update pages based on our own route-data-models do we still need to use keys? if so, what are your thoughts on having multi entires (same route data) of the same page in our stack?
you can do Router.of(context).routerDelegate to access the router delegate directly and calls the public method on the routerdelegate to change selected book.
Alternative, the selected book state can be hosted in an inherited widget and the widget subtree can change it directly, you just need to make sure the routerdelegate is listening to the selected book state and notify its listener when it change.
This works great, but would you happen to know how to apply it in the case of nested routers (to use a BottomNavigationBar) as in this gist? https://gist.github.com/johnpryan/bbca91e23bbb4d39247fa922533be7c9 I had some problems where providing the app state wasn't triggering route changes, as it looks like someone else did in the comments?
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.
Activity
spkersten commentedon Dec 17, 2019
Since the design doc mentioned nested
Navigators, I wonder whether routing could be something extensible, whereNavigatoraren't the only widgets representing part of the route. For example:In our apps, we have a
Navigatorat the root (the one inWidgetsApp) that we use to navigate between onboarding and daily UI. In Daily UI we have a (custom build) tab bar. Each tab has aNavigatorfor navigation within the tab (we want each tab to have an independent stack of pages). For one of the innerNavigators(the one showing settings), we'd like to show a different design on large devices, where the first page is shown on the left of the screen and used to select a page on the right side of the screen (a master-detail view, like the iOS Settings app).To handle deep links, it would be useful if routing could incorporate widgets like a tab bar or a master-detail view.
amreniouinnovent commentedon Jan 21, 2020
@chunhtai What about custom navigation to widgets similar to Fragments in Android?
For example if I have a Form screen with several steps and I want to use navigation between Tabs is it possible I can use Navigator 2.0 but for Tabs?
The same page but using a custom navigator to switch between fragments
https://github.com/amorenew/FlutterBlocFragment
chunhtai commentedon Jan 21, 2020
@amreniouinnovent I am not entirely sure what effect you would like to achieve. I imagine you should be able to achieve most by writing custom url parser with custom page, and on onPopPage.
Can you explain more details on how would you expect to use the api, and what is the effect?
amreniouinnovent commentedon Jan 22, 2020
@chunhtai I expected same like navigation but for a part of a screen
Like fragments in Android
In my Navigation Bloc Fragment, I have the same page but I switch between Sub widgets by my Bloc.
Drawer and AppBar are fixed while widgets are changed.
One more case in Dialogs I have the same dialog and I want a router for the same dialog.
For example, instead of using Indexed Stack widget I want to use routes but for a Scaffold
https://api.flutter.dev/flutter/widgets/IndexedStack-class.html
MajedDH commentedon Jan 25, 2020
@amreniouinnovent Using a navigator as routing inside a scaffold can be achieved by using nested navigators.
Take a look here Flutter Case Study: Multiple Navigators with BottomNavigationBar here's a Demo
amreniouinnovent commentedon Jan 26, 2020
@MajedDH I checked the example it is very good
However that we can achieve that in different ways but not the same as fragments in Android.
What if you want that in a Dialog you will have to add unnecessary complexity for just a simple task.
Android fragments are an awesome and simple way of nested navigation.
I think for now my bloc is good enough but it would be awesome if I could see fragments in Flutter
chunhtai commentedon Jan 29, 2020
@amreniouinnovent That will likely to be a new widget that wraps the navigator to provide more convenient api. I think that should separate from this issue, feel free to file a new feature request
royibernthal commentedon Feb 7, 2020
Hi @chunhtai
How about being able to access the up-to-date context of the current route displayed from within a provider? Do you think it might be relevant?
Here's an issue I opened in which I'm explaining why it's not possible today:
#50231
rrousselGit commentedon Feb 7, 2020
Ah, I forgot to make an issue about that problem.
I agree with @royibernthal that currently (and it'll get worse with Navigator 2.0), showing overlays in response to an InheritedWidget state change is not great.
We had some sort of solution, that is
didChangeDepencencies. But it recently broke on the master channel (see #49527).In my opinion, Navigator 2.0 should also include an Overlay 2.0 with the same reasoning than Navigator:
OverlayEntry is currently imperative, and this is bad.
So it'd be great to have a declarative Overlay manipulation instead.
That's how React deals with overlays.
This would completely solve the "showing overlays in answer to an InheritedWidget change" issue, as it'd just be our typical build method doing its work.
I made an implementation of such declarative Overlay very recently actually: https://github.com/rrousselGit/flutter_portal. It's tested and most features are implemented – feel free to take a look.
It's up to the team to think about it, but I am convinced that this
flutter_portalthing should not be as a package since it's literallyOverlayEntry.Also, all functions like
showDialog,showSnackbar, ..., should be made declarative too, not justOverlayEntry.If needed, I'm open to discussing with the team, make an issue, or potentially make a design doc (although I'd like to avoid the latter – too much work for me).
chunhtai commentedon Feb 10, 2020
@rrousselGit I am not sure if I understand, how would Navigator 2.0 makes the overlay issue worse?
I would like to separate out the overlay entry issue from the navigator refactoring as it the navigator refactor is already pretty complicated. Would you open up a new feature request for merging the library and we can continue our discussion there?
rrousselGit commentedon Feb 18, 2020
Done in #50961
For what it's worth:
I think these two issues are related because if OverlayEntry is declarative, then Navigator is declarative too by default.\
By that I mean
Routerused this way:Is basically the equivalent a declarative
OverlayEntryused this way:with a few extras to handle paths.
It's also worth noting that if such Overlay 2.0 becomes a thing, then it would enable showing "detail" routes from within another route.
This allows anonymous routes while still being declarative, and without having to make
Routeraware of too many things.For example consider our typical Todo app, with two views:
Then with an Overlay 2.0, then we could write:
88 remaining items
chunhtai commentedon Nov 11, 2020
@lukepighetti They meant different things, we separate out the browser history and navigator route stack. The browser back button means build the app with the previous url, and the back button on appbar means means pop the top most route off the route stack.
lukepighetti commentedon Nov 11, 2020
Shouldn't that be the same thing in a 100% declarative router implementation?
chunhtai commentedon Nov 11, 2020
@lukepighetti
Do you mean appbar back button should work the same as browser backward button, or the browser backward button should work the same as appbar back button?
if you meant the former:
The app bar is originally built with imperative API, so we automatically shows the backbutton when there are multiple routes underneath. This mechanism makes sense for mobile application because mobile has the concept of route stack. If you don't want this behavior you can write your own declarative back button
if you meant the latter:
The previous page can be an arbitrary page, it can be a certain page in the app or a page in a completely different website. The browser backward button is used for bring user back to the previous page. It does more than just popping top most route of the app.
lukepighetti commentedon Nov 11, 2020
In a fully declarative router where a single input (ie a url string) always results in the same navigator stack shown on screen, then it seems like there should be no difference between the app back button and the browser back button. The app back button cannot mutate the stack, as the router would no longer be declarative. All it should be able to do is go back one item in the router history. It would be up to us to modify the history if we need to layer things a certain way. This is not the same thing as modifying the navigator stack because it's still 100% declarative.
TLDR the app back button should pop the last history item off the router history, just like the back button. Not mutate the underlying stack by popping a single route/page, because that breaks the promise of being fully declarative.
orestesgaolin commentedon Nov 11, 2020
I think that's not desired. Imagine opening https://navigator_20_example.codemagic.app/#/details/5 and then pressing browser back button. It would be strange to be moved to details/4 or Home. Natural thing to observe would be to go back to this issue.
The AppBar button, however, is very mobile-oriented so it's relatively normal to go back to the previous page within the app i.e. Home.
Edit: one way I can think of would be to add web-oriented AppBar which would imitate the native back button behavior. Or just don't show AppBar's back button on web at all ;)
lukepighetti commentedon Nov 12, 2020
Nothing I've said is unique to browsers, especially since Android has a hardware back button.
The situation you describe would be resolved with a method/delegate that builds the nav history on first load, much like how the current navigator does that with
/onboarding/startbuilding a page stack and route name like this:page stack
//onboarding/onboarding/startroute name
/onboarding/startComparing to what I said, instead of doing pages like that, you'd do history entries. Like this:
route history
//onboarding/onboarding/startWhere the android back button, web back button, or app bar back button pop the current history entry and build the declarative route stack based on the previous (now current) route.
The only time they would differ is when to hide the app bar back button. The web/android back button would eventually take you to the website/app you were on previously, once you've exhausted the Flutter route history.
lukepighetti commentedon Nov 24, 2020
Friendly ping on this. Maybe the ship has sailed, but I fear that Nav 2.0 is a declarative/imperative hybrid instead of fully declarative. It's my understanding that the core design specification called for it to be 100% declarative. I might be missing something, but I think I've given the issue an appropriate amount of care in thinking it through.
chunhtai commentedon Nov 24, 2020
We make it a hybrid for backward compatibility, you can definitely go full declarative by customizing the behavior for android back button in routerdelegate.popRoute.
Milad-Akarie commentedon Nov 24, 2020
@chunhtai do we refrain from awaiting routes for results in favor of passing our own pop functions?
chunhtai commentedon Nov 24, 2020
@Milad-Akarie In a fully declarative world then yes. There are still a lot of widget that relies on imperative push/pop, dialog for example, and they makes sense to stay imperative due to their functionality. In those cases, awaiting for route is still useful.
Milad-Akarie commentedon Nov 26, 2020
@chulwoo-park me again! if we can decide wether or not to update pages based on our own route-data-models do we still need to use keys? if so, what are your thoughts on having multi entires (same route data) of the same page in our stack?
bkoznov commentedon Feb 8, 2021
@chunhtai
This works great, but would you happen to know how to apply it in the case of nested routers (to use a BottomNavigationBar) as in this gist? https://gist.github.com/johnpryan/bbca91e23bbb4d39247fa922533be7c9 I had some problems where providing the app state wasn't triggering route changes, as it looks like someone else did in the comments?
github-actions commentedon Aug 6, 2021
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.[-]Navigator 2.0[/-][+]Router[/+]