parse query string params
This commit is contained in:
parent
3934761f1d
commit
5dbe726593
|
@ -9,6 +9,6 @@ typedef Widget RouteHandler(Map<String, String> parameters);
|
||||||
///
|
///
|
||||||
class AppRoute {
|
class AppRoute {
|
||||||
String route;
|
String route;
|
||||||
RouteCreator routeCreator;
|
RouteHandler handler;
|
||||||
AppRoute(this.route, this.routeCreator);
|
AppRoute(this.route, this.handler);
|
||||||
}
|
}
|
|
@ -1,67 +1,80 @@
|
||||||
part of router;
|
part of router;
|
||||||
|
|
||||||
|
enum TransitionType {
|
||||||
|
native,
|
||||||
|
nativeModal,
|
||||||
|
}
|
||||||
|
|
||||||
class Router {
|
class Router {
|
||||||
/// The tree structure that stores the defined routes
|
/// The tree structure that stores the defined routes
|
||||||
RouteTree _routeTree = new RouteTree();
|
RouteTree _routeTree = new RouteTree();
|
||||||
|
|
||||||
/// Generic handler for when a route has not been defined
|
/// Generic handler for when a route has not been defined
|
||||||
AppRoute notFoundRoute;
|
RouteHandler notFoundHandler;
|
||||||
|
|
||||||
/// Creates a custom [Route] definition
|
|
||||||
void defineRoute(String routePath, {@required RouteCreator creator}) {
|
|
||||||
_routeTree.addRoute(new AppRoute(routePath, creator));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a [PageRoute] definition for the passed [RouteHandler]. You can optionally provide a custom
|
/// Creates a [PageRoute] definition for the passed [RouteHandler]. You can optionally provide a custom
|
||||||
/// transition builder for the route.
|
/// transition builder for the route.
|
||||||
void defineRouteHandler(String routePath, {@required RouteHandler handler, RouteTransitionsBuilder transitionsBuilder,
|
void define(String routePath, {@required RouteHandler handler}) {
|
||||||
Duration duration = const Duration(milliseconds: 250)})
|
_routeTree.addRoute(new AppRoute(routePath, handler));
|
||||||
{
|
|
||||||
RouteCreator creator = (RouteSettings routeSettings, Map<String, String> params) {
|
|
||||||
return new PageRouteBuilder(settings: routeSettings, transitionDuration: duration,
|
|
||||||
transitionsBuilder: transitionsBuilder,
|
|
||||||
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
|
|
||||||
return handler(params);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
_routeTree.addRoute(new AppRoute(routePath, creator));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a [MaterialPageRoute] definition
|
|
||||||
void defineMaterialRoute(String routePath, {@required RouteHandler handler}) {
|
|
||||||
RouteCreator creator = (RouteSettings routeSettings, Map<String, String> params) {
|
|
||||||
return new MaterialPageRoute<Null>(settings: routeSettings, builder: (BuildContext context) {
|
|
||||||
return handler(params);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
_routeTree.addRoute(new AppRoute(routePath, creator));
|
|
||||||
}
|
|
||||||
|
|
||||||
void addRoute(AppRoute route) {
|
|
||||||
_routeTree.addRoute(route);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Finds a defined [AppRoute] for the path value. If no [AppRoute] definition was found
|
||||||
|
/// then function will return null.
|
||||||
AppRoute match(String path) {
|
AppRoute match(String path) {
|
||||||
AppRouteMatch match = _routeTree.matchRoute(path);
|
AppRouteMatch match = _routeTree.matchRoute(path);
|
||||||
return match?.route ?? notFoundRoute;
|
return match?.route;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void navigateTo(BuildContext context, String path, {TransitionType transition = TransitionType.native}) {
|
||||||
|
Route<Null> route;
|
||||||
|
if (transition == TransitionType.native) {
|
||||||
|
route = matchRoute(path);
|
||||||
|
}
|
||||||
|
if (route == null && notFoundHandler != null) {
|
||||||
|
route = _notFoundRoute(context, path);
|
||||||
|
}
|
||||||
|
if (route != null) {
|
||||||
|
Navigator.push(context, route);
|
||||||
|
} else {
|
||||||
|
print("No registered route was found to handle '$path'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
Route<Null> _notFoundRoute(BuildContext context, String path) {
|
||||||
|
RouteCreator creator = (RouteSettings routeSettings, Map<String, String> params) {
|
||||||
|
return new MaterialPageRoute<Null>(settings: routeSettings, builder: (BuildContext context) {
|
||||||
|
return notFoundHandler(params);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return creator(new RouteSettings(name: path), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
Route<Null> matchRoute(String path, {RouteSettings routeSettings = null}) {
|
Route<Null> matchRoute(String path, {RouteSettings routeSettings = null}) {
|
||||||
RouteSettings settingsToUse = routeSettings;
|
RouteSettings settingsToUse = routeSettings;
|
||||||
if (routeSettings == null) {
|
if (routeSettings == null) {
|
||||||
settingsToUse = new RouteSettings(name: path);
|
settingsToUse = new RouteSettings(name: path);
|
||||||
}
|
}
|
||||||
AppRouteMatch match = _routeTree.matchRoute(path);
|
AppRouteMatch match = _routeTree.matchRoute(path);
|
||||||
AppRoute route = match?.route ?? notFoundRoute;
|
AppRoute route = match?.route;
|
||||||
if (route == null) {
|
if (route == null && notFoundHandler == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
RouteHandler handler = (route != null ? route.handler : notFoundHandler);
|
||||||
Map<String, String> parameters = match?.parameters ?? <String, String>{};
|
Map<String, String> parameters = match?.parameters ?? <String, String>{};
|
||||||
return route.routeCreator(settingsToUse, parameters);
|
RouteCreator creator = (RouteSettings routeSettings, Map<String, String> params) {
|
||||||
|
return new MaterialPageRoute<Null>(settings: routeSettings, builder: (BuildContext context) {
|
||||||
|
return handler(params);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return creator(settingsToUse, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// used by the [MaterialApp.onGenerateRoute] function as callback to
|
/// Route generation method. This function can be used as a way to create routes on-the-fly
|
||||||
/// create a route that is able to be consumed.
|
/// if any defined handler is found. It can also be used with the [MaterialApp.onGenerateRoute]
|
||||||
|
/// property as callback to create routes that can be used with the [Navigator] class.
|
||||||
Route<Null> generator(RouteSettings routeSettings) {
|
Route<Null> generator(RouteSettings routeSettings) {
|
||||||
return matchRoute(routeSettings.name, routeSettings: routeSettings);
|
return matchRoute(routeSettings.name, routeSettings: routeSettings);
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,9 +120,17 @@ class RouteTree {
|
||||||
RouteTreeNodeMatch match = new RouteTreeNodeMatch.fromMatch(parentMatch, node);
|
RouteTreeNodeMatch match = new RouteTreeNodeMatch.fromMatch(parentMatch, node);
|
||||||
if (node.isParameter()) {
|
if (node.isParameter()) {
|
||||||
String paramKey = node.part.substring(1);
|
String paramKey = node.part.substring(1);
|
||||||
|
if (checkComponent.contains("?")) {
|
||||||
|
var splitParam = checkComponent.split("?");
|
||||||
|
var namedParam = splitParam[0];
|
||||||
|
var queryParams = parseQueryString(splitParam[1]);
|
||||||
|
match.parameters[paramKey] = namedParam;
|
||||||
|
match.parameters.addAll(queryParams);
|
||||||
|
} else {
|
||||||
match.parameters[paramKey] = checkComponent;
|
match.parameters[paramKey] = checkComponent;
|
||||||
}
|
}
|
||||||
// print("matched: ${node.part}, isParam: ${node.isParameter()}, params: ${match.parameters}");
|
}
|
||||||
|
print("matched: ${node.part}, isParam: ${node.isParameter()}, params: ${match.parameters}");
|
||||||
currentMatches[node] = match;
|
currentMatches[node] = match;
|
||||||
if (node.nodes != null) {
|
if (node.nodes != null) {
|
||||||
nextNodes.addAll(node.nodes);
|
nextNodes.addAll(node.nodes);
|
||||||
|
@ -194,4 +202,15 @@ class RouteTree {
|
||||||
bool _isParameterComponent(String component) {
|
bool _isParameterComponent(String component) {
|
||||||
return component.startsWith(":");
|
return component.startsWith(":");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map<String, String> parseQueryString(String query) {
|
||||||
|
var search = new RegExp('([^&=]+)=?([^&]*)');
|
||||||
|
var params = new Map();
|
||||||
|
if (query.startsWith('?')) query = query.substring(1);
|
||||||
|
decode(String s) => Uri.decodeComponent(s.replaceAll('+', ' '));
|
||||||
|
for (Match match in search.allMatches(query)) {
|
||||||
|
params[decode(match.group(1))] = decode(match.group(2));
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue