问题
I'm building a web-app which needs to have a route that gets a post ID and then it will fetch the post using the ID.
How can I have URL arguments let's say /post/:id
so id is the argument
My app looks like that currently:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// title: "Paste",
initialRoute: "/",
theme: ThemeData(
primarySwatch: Colors.green,
primaryColor: Colors.blue
),
routes: {
"/": (context) => HomePage(),
"/post": (context) => PastieRoute()
},
debugShowCheckedModeBanner: false
);
}
}
EDIT:
This is what I tried according to @BloodLoss and for somereason I don't get anything to the console when accessing localhost:8080/post?id=123
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: "/",
routes: {
"/": (context) => HomePage(),
"/post": (context) => PastieRoute()
},
onGenerateRoute: (settings) {
if (settings.name == "/post") {
print(settings.arguments); // Doesn't fire :(
return MaterialPageRoute(
builder: (context) {
// TODO
}
);
}
},
debugShowCheckedModeBanner: false
);
}
}
回答1:
please follow this link further information https://flutter.dev/docs/cookbook/navigation/navigate-with-arguments
on your MaterialApp
onGenerateRoute: (settings) {
// If you push the PassArguments route
if (settings.name == PassArgumentsScreen.routeName) {
// Cast the arguments to the correct type: ScreenArguments.
final ScreenArguments args = settings.arguments;
// Then, extract the required data from the arguments and
// pass the data to the correct screen.
return MaterialPageRoute(
builder: (context) {
return PassArgumentsScreen(
title: args.title,
message: args.message,
);
},
or you can nativate like web using this plugin fluro
回答2:
I'm new to Flutter, and I found a quirky workaround,...
import 'dart:html';
String itemID;
//My url looks like this,... http://localhost:57887/#item_screen/12345
//Counted 13 characters for '#item_screen/' then got the substring as below
itemID = window.location.hash.substring(13);
print(itemID) //12345
Not very sophisticated, but worked :-D
回答3:
This is how I did it. You can edit it as per your requirements. If you want to use ?q= then use the split by or regex accordingly
Here is the example of both passing in argument as well as passing in url as /topic/:id
Route<dynamic> generateRoute(RouteSettings settings) {
List<String> pathComponents = settings.name.split('/');
final Map<String, dynamic> arguments = settings.arguments;
switch ("/"+pathComponents[1]) {
case shareTopicView:
return MaterialPageRoute(
builder: (context) => TopicPageLayout(topicID: pathComponents[2]));
case internalTopicView:
return MaterialPageRoute(
builder: (context) => TopicPageLayout(topicID: arguments['topicID']));
default:
return MaterialPageRoute(builder: (context) => LandingPage());
}
}
回答4:
tl;dr
//in your example: settings.name = "/post?id=123"
final settingsUri = Uri.parse(settings.name);
//settingsUri.queryParameters is a map of all the query keys and values
final postID = settingsUri.queryParameters['id'];
print(postID); //will print "123"
Drilldown
In a perfect world you would access queryParameters
with Uri.base.queryParameters
because:
Uri.base
Returns the natural base URI for the current platform. When running in a browser this is the current URL of the current page (from window.location.href). When not running in a browser this is the file URI referencing the current working directory.
But currently there is an issue in flutter where you have #/
in your path which messes the Uri.base
interpretation of the Uri.
Follow the issue #33245 until this matter is addressed and you will be able to use Uri.base.queryParameters
回答5:
Here's a workaround that uses the 'default' route as my main route.
I did this because it seems to be the only way that Flutter will allow me to open a URL with an ID in it, that doesn't return a 404.
E.g. Flutter does not seem to respect the '?' separator. So a URL with an ID in it, is read by flutter as an unknown URL. E.g. site.com/invoice?id=999 will return a 404, even in /invoice is set up as route.
My goal: I have a 1-page web app that simply displays a single invoice at a time, which corresponds to the ID in the URL.
My URL
app.com/#/xLZppqzSiSxaFu4PB7Ui
The number at the end of the URL is a FireStore Doc ID.
Here's the code in MyApp:
onGenerateRoute: (settings) {
List<String> pathComponents = settings.name.split('/');
switch (settings.name) {
case '/':
return MaterialPageRoute(
builder: (context) => Invoice(),
);
break;
default:
return MaterialPageRoute(
builder: (context) => Invoice(
arguments: pathComponents.last,
),
);
}
},
This sends 'xLZppqzSiSxaFu4PB7Ui' to the 'Invoice' widget.
回答6:
And here is another way to do it:
My url pattern: www.app.com/#/xLZppqzSiSxaFu4PB7Ui
onGenerateRoute: (settings) {
List<String> pathComponents = settings.name.split('/');
if (pathComponents[1] == 'invoice') {
return MaterialPageRoute(
builder: (context) {
return Invoice(arguments: pathComponents.last);
},
);
} else
return MaterialPageRoute(
builder: (context) {
return LandingPage();
},
);
;
},
来源:https://stackoverflow.com/questions/57552885/how-can-a-named-route-have-url-parameters-in-flutter-web