Browse Source

Merge pull request #31 from goposse/kg-array-params

Support for array parameters
KevinTheGray 7 years ago
parent
commit
70a71b6df6
6 changed files with 44 additions and 25 deletions
  1. 2 2
      README.md
  2. 2 2
      lib/src/common.dart
  3. 3 3
      lib/src/router.dart
  4. 14 8
      lib/src/tree.dart
  5. 1 1
      pubspec.yaml
  6. 22 9
      test/parser_test.dart

+ 2 - 2
README.md

@@ -3,7 +3,7 @@
 
 The brightest, hippest, coolest router for Flutter.
 
-[![Version](https://img.shields.io/badge/version-1.2.1-blue.svg)](https://pub.dartlang.org/packages/fluro)
+[![Version](https://img.shields.io/badge/version-1.2.2-blue.svg)](https://pub.dartlang.org/packages/fluro)
 [![Build Status](https://travis-ci.org/goposse/fluro.svg?branch=master)](https://travis-ci.org/goposse/fluro)
 [![Coverage](https://codecov.io/gh/goposse/fluro/branch/master/graph/badge.svg)](https://codecov.io/gh/goposse/fluro)
 
@@ -40,7 +40,7 @@ var usersHandler = new Handler(handlerFunc: (BuildContext context, Map<String, d
 You should ensure that you add the router as a dependency in your flutter project.
 ```yaml
 dependencies:
- fluro: "^1.2.1"
+ fluro: "^1.2.2"
 ```
 
 You can also reference the git repo directly if you want:

+ 2 - 2
lib/src/common.dart

@@ -21,10 +21,10 @@ class Handler {
 }
 
 ///
-typedef Route<T> RouteCreator<T>(RouteSettings route, Map<String, dynamic> parameters);
+typedef Route<T> RouteCreator<T>(RouteSettings route, Map<String, List<String>> parameters);
 
 ///
-typedef Widget HandlerFunc(BuildContext context, Map<String, dynamic> parameters);
+typedef Widget HandlerFunc(BuildContext context, Map<String, List<String>> parameters);
 
 ///
 class AppRoute {

+ 3 - 3
lib/src/router.dart

@@ -70,7 +70,7 @@ class Router {
 
   ///
   Route<Null> _notFoundRoute(BuildContext context, String path) {
-    RouteCreator<Null> creator = (RouteSettings routeSettings, Map<String, dynamic> parameters) {
+    RouteCreator<Null> creator = (RouteSettings routeSettings, Map<String, List<String>> parameters) {
       return new MaterialPageRoute<Null>(settings: routeSettings, builder: (BuildContext context) {
         return notFoundHandler.handlerFunc(context, parameters);
       });
@@ -93,13 +93,13 @@ class Router {
     if (route == null && notFoundHandler == null) {
       return new RouteMatch(matchType: RouteMatchType.noMatch, errorMessage: "No matching route was found");
     }
-    Map<String, String> parameters = match?.parameters ?? <String, String>{};
+    Map<String, List<String>> parameters = match?.parameters ?? <String, List<String>>{};
     if (handler.type == HandlerType.function) {
       handler.handlerFunc(buildContext, parameters);
       return new RouteMatch(matchType: RouteMatchType.nonVisual);
     }
 
-    RouteCreator creator = (RouteSettings routeSettings, Map<String, dynamic> parameters) {
+    RouteCreator creator = (RouteSettings routeSettings, Map<String, List<String>> parameters) {
       bool isNativeTransition = (transitionType == TransitionType.native || transitionType == TransitionType.nativeModal);
       if (isNativeTransition) {
         return new MaterialPageRoute<dynamic>(settings: routeSettings, fullscreenDialog: transitionType == TransitionType.nativeModal,

+ 14 - 8
lib/src/tree.dart

@@ -18,7 +18,7 @@ class AppRouteMatch {
 
   // properties
   AppRoute route;
-  Map<String, String> parameters = <String, String>{};
+  Map<String, List<String>> parameters = <String, List<String>>{};
 }
 
 class RouteTreeNodeMatch {
@@ -26,7 +26,7 @@ class RouteTreeNodeMatch {
   RouteTreeNodeMatch(this.node);
 
   RouteTreeNodeMatch.fromMatch(RouteTreeNodeMatch match, this.node) {
-    parameters = <String, String>{};
+    parameters = <String, List<String>>{};
     if (match != null) {
       parameters.addAll(match.parameters);
     }
@@ -34,7 +34,7 @@ class RouteTreeNodeMatch {
 
   // properties
   RouteTreeNode node;
-  Map<String, String> parameters = <String, String>{};
+  Map<String, List<String>> parameters = <String, List<String>>{};
 }
 
 class RouteTreeNode {
@@ -121,7 +121,7 @@ class RouteTree {
       List<RouteTreeNode> nextNodes = <RouteTreeNode>[];
       for (RouteTreeNode node in nodesToCheck) {
         String pathPart = checkComponent;
-        Map<String, String> queryMap;
+        Map<String, List<String>> queryMap;
         if (checkComponent.contains("?")) {
           var splitParam = checkComponent.split("?");
           pathPart = splitParam[0];
@@ -133,7 +133,7 @@ class RouteTree {
           RouteTreeNodeMatch match = new RouteTreeNodeMatch.fromMatch(parentMatch, node);
           if (node.isParameter()) {
             String paramKey = node.part.substring(1);
-            match.parameters[paramKey] = pathPart;
+            match.parameters[paramKey] = [pathPart];
           }
           if (queryMap != null) {
             match.parameters.addAll(queryMap);
@@ -211,13 +211,19 @@ class RouteTree {
     return component.startsWith(":");
   }
 
-  Map<String, String> parseQueryString(String query) {
+  Map<String, List<String>> parseQueryString(String query) {
     var search = new RegExp('([^&=]+)=?([^&]*)');
-    var params = new Map();
+    var params = new Map<String, List<String>>();
     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));
+      String key = decode(match.group(1));
+      String value = decode(match.group(2));
+      if (params.containsKey(key)) {
+        params[key].add(value);
+      } else {
+        params[key] = [value];
+      }
     }
     return params;
   }

+ 1 - 1
pubspec.yaml

@@ -1,6 +1,6 @@
 name: fluro
 description: The brightest, hippest, coolest router for Flutter.
-version: 1.2.1
+version: 1.2.2
 author: Posse Productions LLC <apps@goposse.com>
 homepage: https://github.com/goposse/fluro
 

+ 22 - 9
test/parser_test.dart

@@ -16,8 +16,8 @@ void main() {
     Router router = new Router();
     router.define(route, handler: null);
     AppRouteMatch match = router.match(path);
-    expect(match?.parameters, equals(<String, String>{
-      "id" : "1234",
+    expect(match?.parameters, equals(<String, List<String>>{
+      "id" : ["1234"],
     }));
   });
 
@@ -27,9 +27,9 @@ void main() {
     Router router = new Router();
     router.define(route, handler: null);
     AppRouteMatch match = router.match(path);
-    expect(match?.parameters, equals(<String, String>{
-      "id" : "1234",
-      "name" : "luke",
+    expect(match?.parameters, equals(<String, List<String>>{
+      "id" : ["1234"],
+      "name" : ["luke"],
     }));
   });
 
@@ -39,10 +39,23 @@ void main() {
     Router router = new Router();
     router.define(route, handler: null);
     AppRouteMatch match = router.match(path);
-    expect(match?.parameters, equals(<String, String>{
-      "name" : "luke",
-      "phrase" : "hello world",
-      "number" : "7",
+    expect(match?.parameters, equals(<String, List<String>>{
+      "name" : ["luke"],
+      "phrase" : ["hello world"],
+      "number" : ["7"],
+    }));
+  });
+
+  testWidgets("Router correctly parses array parameters", (WidgetTester tester) async {
+    String path = "/users/create?name=luke&phrase=hello%20world&number=7&number=10&number=13";
+    String route = "/users/create";
+    Router router = new Router();
+    router.define(route, handler: null);
+    AppRouteMatch match = router.match(path);
+    expect(match?.parameters, equals(<String, List<String>>{
+      "name" : ["luke"],
+      "phrase" : ["hello world"],
+      "number" : ["7", "10", "13"],
     }));
   });