Reputation: 1233
In a vanilla flutter I use to pass multiple parameters to other screen like this:
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => CatalogFilterPage(
list: list,
bloc: bloc,
)))
Pretty simple and easy. I can pass 2 needed parameters, list and bloc. After use it in CatalogFilterPage.
Now after switching to go_router and looking through documentation I can't seem to find how to pass multiple data. Even passing single object seems not that good:
onTap: () =>
context.pushNamed('SelectedCatalogItem', extra: list[index]),
And in router I have to use casting to set correct type:
builder: (context, state) => SelectedCatalogItem(
item: state.extra as ListItemsModel,
),
It was fine for single parameter. But now I don't have an idea how to pass multiple parameters. How can I do it? Is even passing parameters, like models, as an extra is right way?
P.S. I know that you can pass parameters as context.pushNamed('CatalogFilterPage', params: ___)
, but params
has type of Map<String, String> witch not let me pass model's
Upvotes: 72
Views: 99918
Reputation: 79
You can use extra and pass to it map like this
GoRoute(
path: '/path',
name: 'path-name',
builder: (context, state) {
Map<String, dynamic> extra =
state.extra as Map<String, dynamic>;
return ScreenName(
par1: extra['par1'],
par2: extra['par2'],
);
},
),
and call it like this
context.goNamed(
'path-name',
extra: {
'par1': object1,
'par2': object2,
},
),
Upvotes: 1
Reputation: 24920
Below Go Router 7 i.e < 7.0.0 use `params`, `queryParams`
Go Router 7 to 10 i.e 7.0.0 <=, < 10.0.0 use `pathParameters`, `queryParameters`
Above Go Router 10 i.e 10.0.0 <= use `pathParameters`, `uri.queryParameters`
There are three ways: pathParameters
, queryParameters
, extra
pathParameters
path = '/routeName/:id1/:id2'
uri.queryParameters
path = '/routeName'
extra
object
pathParameters
When you know number of params beforehand use pathParameters
prop in context.goNamed()
GoRoute(
path: '/sample/:id1/:id2', // 👈 Defination of params in the path is important
name: 'sample',
builder: (context, state) => SampleWidget(
id1: state.pathParameters['id1'],
id2: state.pathParameters['id2'],
),
),
ElevatedButton(
onPressed: () {
var param1 = "param1";
var param2 = "param2";
context.goNamed("sample", pathParameters: {'id1': param1, 'id2': param2});
},
child: const Text("Hello"),
),
class SampleWidget extends StatelessWidget {
String? id1;
String? id2;
SampleWidget({super.key, this.id1, this.id2});
@override
Widget build(BuildContext context) {
...
}
}
uri.queryParameters
Use the queryParameters
in context.goNamed()
ex: context.goNamed('sample', queryParameters: {'id1': 'param1'})
function or
simply add params after the ? in the URL of context.go()
ex: context.go('/sample?id1=param1')
.
The best thing about queryParameters
is that you don't have to explicitly define them in your route path and can easily access them using the state.uri.queryParameters
method. You can add miscellaneous user-related data as a query parameter.
GoRoute(
name: "sample",
path: "/sample",
builder: (context, state) => SampleWidget(
id1: state.uri.queryParameters['id1'],
id2: state.uri.queryParameters['id2'],
),
)
ElevatedButton(
onPressed: () {
var param1 = "param1";
var param2 = "param2";
context.goNamed("sample", queryParameters: {'id1': param1, 'id2': param2});
// context.go("/sample?id1=$param1&id2=$param2"); 👈 or like this.
},
child: const Text("Hello"),
),
class SampleWidget extends StatelessWidget {
String? id1;
String? id2;
SampleWidget({super.key, this.id1, this.id2});
@override
Widget build(BuildContext context) {
...
}
}
extra
Use this when you want to pass a model/object
between routes
GoRoute(
path: '/sample',
builder: (context, state) {
Sample sample = state.extra as Sample; // 👈 casting is important
return GoToScreen(object: sample);
},
),
Refer https://stackoverflow.com/a/74813017/13431819 for passing object
between routes
Upvotes: 204
Reputation: 101
Here is a solution with my own code. In my case, i want to parse MenuModels
from HomeScreen
to another screen (ItemScreen
):
context.push(
'/item-screen',
extra: widget.menuModels,
),
And in my route.dart
GoRoute(
path: '/item-screen',
builder: (context, state) {
MenuModels models = state.extra as MenuModels;
return ItemScreen(
menuModels: models,
);
},
),
Upvotes: 10
Reputation: 213
I am new to Flutter, but here is how I passed multiple parameters/arguments to a route with GoRouter using the extra
property of context.push()
:
// navigate to /my-path, pass 2 arguments to context.state.extra
context.push("/my-path", extra: {"arg1": firstArg, "arg2": secondArg});
Then, inside my route:
// ...
// Use arguments in builder of the GoRoute
GoRoute(
path: '/dashboard',
builder: (context, state) {
Map<String, MyCustomType> args =
state.extra as Map<String, MyCustomType>;
return MyWidget(arg1: args["arg1"]!, arg2: args["arg2"]!);
}
),
// ...
Upvotes: 13
Reputation: 94
From the go_router documentation we can see that:
The extra object is useful if you'd like to simply pass along a single object to the builder function w/o passing an object identifier via a URI and looking up the object from a store.
What you can do instead is pass in the id/name of the 'SelectedCatalogItem' as params and form the Object later on (if possible). The 'params' parameter lets us pass in more than one fields
onTap: () => context.pushNamed('SelectedCatalogItem',
params: {"id":list[index].id.toString(),"name":list[index].name}),
Then in the builder function of the GoRouter we can do:
GoRoute(
path: 'selectedCatalogItem/view/:id/:name',
name: 'SelectedCatalogItem',
builder: (context, state){
int id = int.parse(state.params['id']!);
String name = state.params['name']!;
// use id and name to your use...
});
Upvotes: 4