| OLD | NEW |
| 1 /** | 1 /** |
| 2 * The [routing] library makes it easier to build large single-page applications
. The | 2 * The [routing] library makes it easier to build large single-page |
| 3 * library lets you map the browser address bar to semantic structure of your | 3 * applications. The library lets you map the browser address bar to semantic |
| 4 * application and keeps them in sync. | 4 * structure of your application and keeps them in sync. |
| 5 * | 5 * |
| 6 * Angular uses the [route_hierarchical] package to define application routes an
d | 6 * Angular uses the [route_hierarchical] package to define application routes |
| 7 * to provide custom tools to make it easier to use routing with Angular templat
es. | 7 * and to provide custom tools to make it easier to use routing with Angular |
| 8 * templates. |
| 8 * | 9 * |
| 9 * Lets consider a simple recipe book application. The application might have | 10 * Lets consider a simple recipe book application. The application might have |
| 10 * the following pages: | 11 * the following pages: |
| 11 * | 12 * |
| 12 * * recipes list/search | 13 * * recipes list/search |
| 13 * * add new recipe | 14 * * add new recipe |
| 14 * * view recipe | 15 * * view recipe |
| 15 * * edit recipe | 16 * * edit recipe |
| 16 * | 17 * |
| 17 * Each of those pages can be represented by an address: | 18 * Each of those pages can be represented by an address: |
| 18 * | 19 * |
| 19 * * `/recipes` | 20 * * `/recipes` |
| 20 * * `/addRecipe` | 21 * * `/addRecipe` |
| 21 * * `/recipe/:recipeId/view` | 22 * * `/recipe/:recipeId/view` |
| 22 * * `/recipe/:recipeId/edit` | 23 * * `/recipe/:recipeId/edit` |
| 23 * | 24 * |
| 24 * | 25 * |
| 25 * Lets try to define those routes in Angular. To get started we need to | 26 * Lets try to define those routes in Angular. To get started we need to |
| 26 * provide an implementation of [RouteInitializer] interface. | 27 * provide an implementation of [RouteInitializerFn] function. |
| 27 * | 28 * |
| 28 * class RecipesRouteInitializer implements RouteInitializer { | 29 * void initRoutes(Router router, ViewFactory view) { |
| 29 * void init(Router router, ViewFactory view) { | 30 * // define routes here. |
| 30 * // define routes here. | 31 * } |
| 31 * } | |
| 32 * } | |
| 33 * | 32 * |
| 34 * var module = new Module() | 33 * var module = new Module() |
| 35 * ..type(RouteInitializer, implementedBy: RecipesRouteInitializer); | 34 * ..factory(RouteInitializerFn, (_) => initRoutes); |
| 36 * | 35 * |
| 37 * Lets see how we could define our routes using the routing framework: | 36 * Lets see how we could define our routes using the routing framework: |
| 38 * | 37 * |
| 39 * class RecipesRouteInitializer implements RouteInitializer { | 38 * void initRoutes(Router router, ViewFactory view) { |
| 40 * void init(Router router, ViewFactory view) { | 39 * router |
| 41 * router | 40 * ..addRoute( |
| 42 * ..addRoute( | 41 * name: 'recipes', |
| 43 * name: 'recipes', | 42 * path: '/recipes', |
| 44 * path: '/recipes', | 43 * enter: view('recipes.html')) |
| 45 * enter: view('recipes.html')) | 44 * ..addRoute( |
| 46 * ..addRoute( | 45 * name: 'addRecipe', |
| 47 * name: 'addRecipe', | 46 * path: '/addRecipe', |
| 48 * path: '/addRecipe', | 47 * enter: view('addRecipe.html')) |
| 49 * enter: view('addRecipe.html')) | 48 * ..addRoute( |
| 50 * ..addRoute( | 49 * name: 'viewRecipe', |
| 51 * name: 'viewRecipe', | 50 * path: '/recipe/:recipeId/view', |
| 52 * path: '/recipe/:recipeId/view', | 51 * enter: view('viewRecipe.html')) |
| 53 * enter: view('viewRecipe.html')) | 52 * ..addRoute( |
| 54 * ..addRoute( | 53 * name: 'editRecipe', |
| 55 * name: 'editRecipe', | 54 * path: '/recipe/:recipeId/edit', |
| 56 * path: '/recipe/:recipeId/edit', | 55 * enter: view('editRecipe.html')); |
| 57 * enter: view('editRecipe.html')); | |
| 58 * } | |
| 59 * } | 56 * } |
| 60 * | 57 * |
| 61 * We defined 4 routes and for each route we set views (templates) to be | 58 * We defined 4 routes and for each route we set views (templates) to be |
| 62 * displayed when that route is "entered". For example, when the browser URL | 59 * displayed when that route is "entered". For example, when the browser URL |
| 63 * is set to `/recipes`, the `recipes.html` will be displayed. | 60 * is set to `/recipes`, the `recipes.html` will be displayed. |
| 64 * | 61 * |
| 65 * You have to tell Angular where to load views by putting `<ng-view>` tag in | 62 * You have to tell Angular where to load views by putting `<ng-view>` tag in |
| 66 * you template. | 63 * you template. |
| 67 * | 64 * |
| 68 * Notice that `viewRecipe` and `editRecipe` route paths have `recipeId` | 65 * Notice that `viewRecipe` and `editRecipe` route paths have `recipeId` |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 * easier. For example, notice that we didn't need to manually call | 114 * easier. For example, notice that we didn't need to manually call |
| 118 * [StreamSubscription.cancel] for subscription to [Route.onLeave]. Calling | 115 * [StreamSubscription.cancel] for subscription to [Route.onLeave]. Calling |
| 119 * [RouteHandle.discard] unsubscribes all listeneters created for the handle. | 116 * [RouteHandle.discard] unsubscribes all listeneters created for the handle. |
| 120 * | 117 * |
| 121 * | 118 * |
| 122 * # Hierarchical Routes | 119 * # Hierarchical Routes |
| 123 * | 120 * |
| 124 * The routing framework allows us to define trees of routes. In our recipes | 121 * The routing framework allows us to define trees of routes. In our recipes |
| 125 * example we could have defined our routes like this: | 122 * example we could have defined our routes like this: |
| 126 * | 123 * |
| 127 * class RecipesRouteInitializer implements RouteInitializer { | 124 * void initRoutes(Router router, ViewFactory view) { |
| 128 * void init(Router router, ViewFactory view) { | 125 * router |
| 129 * router | 126 * ..addRoute( |
| 130 * ..addRoute( | 127 * name: 'recipes', |
| 131 * name: 'recipes', | 128 * path: '/recipes', |
| 132 * path: '/recipes', | 129 * enter: view('recipes.html')) |
| 133 * enter: view('recipes.html')) | 130 * ..addRoute( |
| 134 * ..addRoute( | 131 * name: 'addRecipe', |
| 135 * name: 'addRecipe', | 132 * path: '/addRecipe', |
| 136 * path: '/addRecipe', | 133 * enter: view('addRecipe.html')) |
| 137 * enter: view('addRecipe.html')) | 134 * ..addRoute( |
| 138 * ..addRoute( | 135 * name: 'recipe', |
| 139 * name: 'recipe', | 136 * path: '/recipe/:recipeId', |
| 140 * path: '/recipe/:recipeId', | 137 * mount: (Route route) => route |
| 141 * mount: (Route route) => route | 138 * ..addRoute( |
| 142 * ..addRoute( | 139 * name: 'view', |
| 143 * name: 'view', | 140 * path: '/view', |
| 144 * path: '/view', | 141 * enter: view('viewRecipe.html')) |
| 145 * enter: view('viewRecipe.html')) | 142 * ..addRoute( |
| 146 * ..addRoute( | 143 * name: 'edit', |
| 147 * name: 'edit', | 144 * path: '/edit', |
| 148 * path: '/edit', | 145 * enter: view('editRecipe.html'))); |
| 149 * enter: view('editRecipe.html'))); | |
| 150 * } | |
| 151 * } | 146 * } |
| 147 * } |
| 152 */ | 148 */ |
| 153 library angular.routing; | 149 library angular.routing; |
| 154 | 150 |
| 155 import 'dart:async'; | 151 import 'dart:async'; |
| 156 import 'dart:html'; | 152 import 'dart:html'; |
| 157 | 153 |
| 158 import 'package:di/di.dart'; | 154 import 'package:di/di.dart'; |
| 159 import 'package:angular/angular.dart'; | 155 import 'package:angular/angular.dart'; |
| 160 import 'package:route_hierarchical/client.dart'; | 156 import 'package:route_hierarchical/client.dart'; |
| 161 export 'package:route_hierarchical/client.dart'; | 157 export 'package:route_hierarchical/client.dart'; |
| 162 | 158 |
| 163 part 'routing.dart'; | 159 part 'routing.dart'; |
| 164 part 'ng_view.dart'; | 160 part 'ng_view.dart'; |
| 165 part 'ng_bind_route.dart'; | 161 part 'ng_bind_route.dart'; |
| 166 | 162 |
| 167 class NgRoutingModule extends Module { | 163 class NgRoutingModule extends Module { |
| 168 NgRoutingModule({bool usePushState: true}) { | 164 NgRoutingModule({bool usePushState: true}) { |
| 169 type(NgRoutingUsePushState); | 165 type(NgRoutingUsePushState); |
| 170 factory(Router, (injector) { | 166 factory(Router, (injector) { |
| 171 var useFragment = !injector.get(NgRoutingUsePushState).usePushState; | 167 var useFragment = !injector.get(NgRoutingUsePushState).usePushState; |
| 172 return new Router(useFragment: useFragment, | 168 return new Router(useFragment: useFragment, |
| 173 windowImpl: injector.get(Window)); | 169 windowImpl: injector.get(Window)); |
| 174 }); | 170 }); |
| 175 type(NgRoutingHelper); | 171 type(NgRoutingHelper); |
| 176 value(RouteProvider, null); | 172 value(RouteProvider, null); |
| 177 value(RouteInitializer, null); | 173 value(RouteInitializer, null); |
| 174 value(RouteInitializerFn, null); |
| 178 | 175 |
| 179 // directives | 176 // directives |
| 180 value(NgViewDirective, null); | 177 value(NgViewDirective, null); |
| 181 type(NgBindRouteDirective); | 178 type(NgBindRouteDirective); |
| 182 } | 179 } |
| 183 } | 180 } |
| 184 | 181 |
| 185 /** | 182 /** |
| 186 * Allows configuration of [Router.useFragment]. By default [usePushState] is | 183 * Allows configuration of [Router.useFragment]. By default [usePushState] is |
| 187 * true, so the router will listen to [Window.onPopState] and route URLs like | 184 * true, so the router will listen to [Window.onPopState] and route URLs like |
| 188 * "http://host:port/foo/bar?baz=qux". Both the path and query parts of the URL | 185 * "http://host:port/foo/bar?baz=qux". Both the path and query parts of the URL |
| 189 * are used by the router. If [usePushState] is false, router will listen to | 186 * are used by the router. If [usePushState] is false, router will listen to |
| 190 * [Window.onHashChange] and route URLs like | 187 * [Window.onHashChange] and route URLs like |
| 191 * "http://host:port/path#/foo/bar?baz=qux". Everything after hash (#) is used | 188 * "http://host:port/path#/foo/bar?baz=qux". Everything after hash (#) is used |
| 192 * by the router. | 189 * by the router. |
| 193 */ | 190 */ |
| 194 @NgInjectableService() | 191 @NgInjectableService() |
| 195 class NgRoutingUsePushState { | 192 class NgRoutingUsePushState { |
| 196 final bool usePushState; | 193 final bool usePushState; |
| 197 NgRoutingUsePushState(): usePushState = true; | 194 NgRoutingUsePushState(): usePushState = true; |
| 198 NgRoutingUsePushState.value(this.usePushState); | 195 NgRoutingUsePushState.value(this.usePushState); |
| 199 } | 196 } |
| OLD | NEW |