24

I'm trying to open a page and get returned result with go_router package. In Navigation 1.0 I use this:

final result = await Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => const SecondRoute()),
);
// handle result

But I can't seem to do it with go_router. Any solution or explaination?

krishnaacharyaa
  • 14,953
  • 4
  • 49
  • 88
dante
  • 984
  • 3
  • 10
  • 24

10 Answers10

11

The latest version of go_router package now supports this functionality. To pass data when popping from a screen, you can do this:

context.pop('value');

And to get this value back, your code should look like this:

String? val = await context.pushNamed('secondRoute');

Hope this helps, thank you

Aditya Arora
  • 351
  • 2
  • 7
9

You can do this with GoRouter.of(context).addListener.

First you push your new page and add a listener afterwards

GoRouter.of(context).push("/page/${page!.id}/edit");
GoRouter.of(context).addListener(watchRouteChange);

The listener function can look something like this

  watchRouteChange() {
    if (!GoRouter.of(context).location.contains("/edit")) {  // Here you check for some changes in your route that indicate you are no longer on the page you have pushed before
      // do something
      GoRouter.of(context).removeListener(watchRouteChange); // remove listener
    }
  }


Jonas
  • 7,089
  • 15
  • 49
  • 110
3

Presently there is no way to achieve this using go_router. You can use go_router_flow which is exactly like go_router with this pop with value feature.

final bool? result = await context.push<bool>('/page2');

WidgetsBinding.instance.addPostFrameCallback((_) {
  if(result){
    print('Page returned $result');
  }
});
krishnaacharyaa
  • 14,953
  • 4
  • 49
  • 88
2

You can use the callback by putting the function in extra object when push new screen.

Example Screen A -push-> Screen B ->pop with result -> Screen A (get results)

  1. Define the function type to put


typedef AddNewEventResult = void Function(Result result);


  1. Push A -> B


GoRoute(
path: kScreenB,
builder: (BuildContext context, GoRouterState state) => ScreenB(addNewEventResultstate.extra! as AddNewEventResult),
)


  1. When screen B has done, just pop from B to A and attached the result (Result)


Navigator.of(context).pop();
widget.addNewEventResult(true, Result());


Võ Anh Kiệt
  • 369
  • 2
  • 9
1

Unfortunately, the functionality you are looking for is not provided by GoRouter at this time.

An alternative to using go_router_flow is to implement something simple yourself by passing callbacks as the extra property on GoRouterState.

This dartpad contains a full example, but the gist is that you define your routes similar to:

GoRouter(
  initialLocation: "/",
  routes: <RouteBase>[
    GoRoute(
      path: "/second",
      builder: (_, state) {
        final params = state.extra! as SecondPageParams;

        return SecondPage(params: params);
      },
    ),
  ],
);

And define your SecondPage similar to:

class SecondPageParams {
  final void Function(String data) action;
  
  const SecondPageParams(this.action);
}

class SecondPage extends StatelessWidget {
  final SecondPageParams params;

  const SecondPage({super.key, required this.params});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: ElevatedButton(
            onPressed: () {
              context.pop();
              params.action("Data from second page");
            },
            child: const Text("Pop and perform action")
          ),
        ),
      ),
    );
  }
}

It's not as clean as being able to await a context.push, but this is a simple way you can specify the action that you want to take whenever SecondPage is popped off the stack without having to rely on a different package.

mun
  • 11
  • 2
0

As of answer time, only support for doing

 List<Archive> selectArchives = await Navigator.of(context).push(
            MaterialPageRoute(
                builder: (context) => const ArchiveListPage(
                    selectMode: true, canSelectCount: 1)));

 context.pop(_selectArchives);
Zhuoyuan.Li
  • 318
  • 2
  • 10
0

in the documentation : https://pub.dev/documentation/go_router/latest/topics/Navigation-topic.html

Waiting for a value to be returned:

onTap: () {
  final bool? result = await context.push<bool>('/page2');
  if(result ?? false)...
}

Returning a value:

onTap: () => context.pop(true)
Anthony
  • 1,155
  • 10
  • 17
-1

This flow is described in the docs here: https://gorouter.dev/user-input

Generally you have to update the data and return some value back as a route with params and the screen itself should manage updates / data manipulation.

I don't want to copy paste their code here, but the answer you are looking for is in the docs page above.

Updated with link from archive: https://web.archive.org/web/20220325235726/https://gorouter.dev/user-input

Thanks ahmetakil

Oleg Novosad
  • 2,261
  • 1
  • 27
  • 28
  • 1
    I didn't get it that using user input. Can you please add code here to get data back from screen 2 to screen 1 (previous screen) ? – MaheshPeri19 Apr 17 '22 at 09:02
  • @MaheshPeri19 please follow docs, they are well documented & self-explainable. – Oleg Novosad Apr 19 '22 at 09:03
  • 1
    As I understand, the documentation basically says that there is no way to await a result using the go_router. It suggests you do the data handling in the "user input page" and navigate away when you saved the data without returning to the original page. This means you can't do a simple picker screen (in my case pick a place from a full-screen map). The only way you can do this is to use the plain navigator API and handle everything manually (eg.: navigation guards, route-based providers that are injected by the router, etc.). – Krisztián Velez May 12 '22 at 13:48
  • Theres an open issue here: https://github.com/flutter/flutter/issues/99663. It might solve your problem once its done. – novas1r1 May 25 '22 at 11:07
  • @OlegNovosad context.pop() stated on that page doesn't really go back the browser history, instead it is going to a new page. The documentation isn't really well documented for me. – Unreality Sep 18 '22 at 22:42
  • I found that if you want to go back successfully by context.pop(), you would need to use context.push('path') instead of context.go('path'). However, on that documentation page it paired context.pop with context.go, which is confusing to me – Unreality Sep 18 '22 at 22:57
  • Would like to mention to the commenters that I'm not the representative of the go_router :) I found that if you follow documentation properly - it can solve the issues with navigation. – Oleg Novosad Oct 22 '22 at 07:31
  • You should've added the code here because the link is not working anymore. – Sprint Nov 17 '22 at 04:12
  • @Sprint thanks for your comment. From what I've found is that Flutter team is adopting go_router package and though they disabled the original website and the new one is located here: https://pub.dev/documentation/go_router/latest/topics/Get%20started-topic.html but it does not have that information so far. Will search for a code sample. – Oleg Novosad Nov 17 '22 at 09:47
  • 1
    link is not working anymore – Chris Nov 18 '22 at 11:35
  • 2
    Here is a web archive link since the website is not working at the moment https://web.archive.org/web/20220325235726/https://gorouter.dev/user-input – ahmetakil Nov 22 '22 at 14:21
-3

if you use Gorouter you can use

GoRouter.of(context).pop();

  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 02 '23 at 19:08
-7

When you are done with the next screen just use Navigator.pop(context,true); and true is something that you want to send to the previous screen. You can send anything I'm just using true for reference. This will allow your result variable to get data and perform anything.

Usama majid
  • 186
  • 16
  • You need to access the returned data from the 2nd page on the 1st page? Is that what you were trying to say ? – Usama majid Mar 05 '22 at 06:50
  • I'm asking about go_router package. Not how Navigator.push Navigator.pop work, I know this. go_router do not return Future like Navigation 1.0 – dante Mar 05 '22 at 06:52