5

I have used Fluro package inside my Flutter app, and I implemented all of my routes with a handler like the example of this package. Could you please let me know what is the correct way to pass an object or list of objects between routes?

Erfan Jazeb Nikoo
  • 978
  • 3
  • 12
  • 36

4 Answers4

4

You could do that via ModalRoute.of(context).settings.arguments

so if you have object:

class ScreenArguments {
  final String title;
  ScreenArguments(this.title);
}

navigate with:

Navigator.of(context).pushNamed("/screen", arguments: ScreenArguments("Title"));

and in handler:

static Handler _screenHandler = Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) {
    final ScreenArguments args = ModalRoute.of(context).settings.arguments;
    return PassArgumentsScreen(args?.title);
});

Adelina
  • 10,915
  • 1
  • 38
  • 46
2

The solution presented at How to pass JSON response to another view works unless your object has a string (or the decoded JSON contains) a / as @Chirag said.

I'm giving my solution as it worked, since my object has an URL inside.

Given the router:

_router.define("/groups/:group", handler: Handler(handlerFunc: (context, params) {
  String param = params["group"][0];
  GroupAPIModel group = GroupAPIModel.fromJson(decodeJsonDataForFluro(param));
  return GroupDetailsScreen(group);
}));

Defining:

String encodeJsonDataForFluro(Map<String, dynamic> mapToEncode) {
  return jsonEncode(mapToEncode).replaceAll("/", HtmlEscape().convert("/"));
} 

Map<String, dynamic> decodeJsonDataForFluro(String encodedMap) {
  return jsonDecode(encodedMap.replaceAll(HtmlEscape().convert("/"), "/"));
}

This method would reach that route:

void _onGroupClicked(GroupAPIModel group) {
  String bodyJson = encodeJsonDataForFluro(group.toJson());
  router.navigateTo(context: context, path: "/groups/$bodyJson");
}
Rafael Ruiz Muñoz
  • 5,333
  • 6
  • 46
  • 92
2

Just struggled with this and found a solution. You can do this:

Object object = <Your Object>
Navigator.of(context).pushNamed("/page/" + object.id.toString(),
        arguments: object);

And then access the custom object in Fluro like this:

  static void setupRouter() {
    router.define("page/:pageId", handler: _pageHandler);
  }

  static Handler _pageHandler =
      Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) {
    Object object = ModalRoute.of(context).settings.arguments;
    return Widget(object);
  });

While Fluro doesn't have this, this is a solution that isn't completely terrible.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Florian
  • 226
  • 1
  • 9
2

I used to pass the data as an encoded JSON and String format like all other solutions in this question. Recently, the Fluro plugin provides a way of pass arguments as a class object between the routes like a Flutter navigator.

After pushing a route with a custom RouteSettings you can use the BuildContext.settings extension to extract the settings. Typically this would be done in Handler.handlerFunc so you can pass RouteSettings.arguments to your screen widgets.

/// Push a route with custom RouteSettings if you don't want to use path params
FluroRouter.appRouter.navigateTo(
  context,
  'home',
  routeSettings: RouteSettings(
    arguments: MyArgumentsDataClass('foo!'),
  ),
);

/// Extract the arguments using [BuildContext.settings.arguments] or [BuildContext.arguments] for short
var homeHandler = Handler(
  handlerFunc: (context, params) {
    final args = context.settings.arguments as MyArgumentsDataClass;

    return HomeComponent(args);
  },
);

In the case of using the Flutter navigator instead of the Fluro plugin use this link or check the following approach.

The Navigator provides the ability to navigate to a named route from any part of an app using a common identifier. In some cases, you might also need to pass arguments to a named route. For example, you might wish to navigate to the /user route and pass information about the user to that route.

To pass different pieces of data, create a class that stores this information.

// You can pass any object to the arguments parameter.
// In this example, create a class that contains a customizable
// title and message.
class ScreenArguments {
  final String title;
  final String message;

  ScreenArguments(this.title, this.message);
}

Now you need to define a handler using ModalRoute:

static Handler _screenHandler = Handler(
    handlerFunc: (BuildContext context, Map<String, dynamic> params) {
      final ScreenArguments args = ModalRoute
          .of(context)
          .settings
          .arguments;
      return PassArgumentsScreen(args?.title);
    });

And navigate with:

Navigator.pushNamed(
      context,
      "/screen",
      arguments: ScreenArguments(
        'Class Arguments Screen',
        'This message is extracted in the build method.',
      ),
    );
Erfan Jazeb Nikoo
  • 978
  • 3
  • 12
  • 36