| OLD | NEW |
| (Empty) | |
| 1 part of angular.routing; |
| 2 |
| 3 /** |
| 4 * A directive that works with the [Router] and loads the template associated |
| 5 * with the current route. |
| 6 * |
| 7 * <ng-view></ng-view> |
| 8 * |
| 9 * [NgViewDirective] can work with [NgViewDirective] to define nested views |
| 10 * for hierarchical routes. For example: |
| 11 * |
| 12 * class MyRouteInitializer implements RouteInitializer { |
| 13 * void init(Router router, ViewFactory view) { |
| 14 * router.root |
| 15 * ..addRoute( |
| 16 * name: 'library', |
| 17 * path: '/library', |
| 18 * enter: view('library.html'), |
| 19 * mount: (Route route) => route |
| 20 * ..addRoute( |
| 21 * name: 'all', |
| 22 * path: '/all', |
| 23 * enter: view('book_list.html')) |
| 24 * ..addRoute( |
| 25 * name: 'book', |
| 26 * path: '/:bookId', |
| 27 * mount: (Route route) => route |
| 28 * ..addRoute( |
| 29 * name: 'overview', |
| 30 * path: '/overview', |
| 31 * defaultRoute: true, |
| 32 * enter: view('book_overview.html')) |
| 33 * ..addRoute( |
| 34 * name: 'read', |
| 35 * path: '/read', |
| 36 * enter: view('book_read.html')))); |
| 37 * } |
| 38 * } |
| 39 * |
| 40 * index.html: |
| 41 * |
| 42 * <ng-view></ng-view> |
| 43 * |
| 44 * library.html: |
| 45 * |
| 46 * <div> |
| 47 * <h1>Library!</h1> |
| 48 * |
| 49 * <ng-view></ng-view> |
| 50 * </div> |
| 51 * |
| 52 * book_list.html: |
| 53 * |
| 54 * <ul> |
| 55 * <li><a href="/library/12345/overview">Book 12345</a> |
| 56 * <li><a href="/library/23456/overview">Book 23456</a> |
| 57 * </ul> |
| 58 */ |
| 59 @NgDirective( |
| 60 selector: 'ng-view', |
| 61 publishTypes: const [RouteProvider], |
| 62 visibility: NgDirective.CHILDREN_VISIBILITY |
| 63 ) |
| 64 class NgViewDirective implements NgDetachAware, RouteProvider { |
| 65 final NgRoutingHelper locationService; |
| 66 final BlockCache blockCache; |
| 67 final Scope scope; |
| 68 final Injector injector; |
| 69 final Element element; |
| 70 RouteHandle _route; |
| 71 |
| 72 Block _previousBlock; |
| 73 Scope _previousScope; |
| 74 Route _viewRoute; |
| 75 |
| 76 NgViewDirective(this.element, this.blockCache, this.scope, Injector injector,
Router router) |
| 77 : injector = injector, locationService = injector.get(NgRoutingHelper) { |
| 78 RouteProvider routeProvider = injector.parent.get(NgViewDirective); |
| 79 if (routeProvider != null) { |
| 80 _route = routeProvider.route.newHandle(); |
| 81 } else { |
| 82 _route = router.root.newHandle(); |
| 83 } |
| 84 locationService._registerPortal(this); |
| 85 _maybeReloadViews(); |
| 86 } |
| 87 |
| 88 void _maybeReloadViews() { |
| 89 if (_route.isActive) { |
| 90 locationService._reloadViews(startingFrom: _route); |
| 91 } |
| 92 } |
| 93 |
| 94 detach() { |
| 95 _route.discard(); |
| 96 locationService._unregisterPortal(this); |
| 97 } |
| 98 |
| 99 _show(String templateUrl, Route route) { |
| 100 assert(route.isActive); |
| 101 |
| 102 if (_viewRoute != null) return; |
| 103 _viewRoute = route; |
| 104 |
| 105 StreamSubscription _leaveSubscription; |
| 106 _leaveSubscription = route.onLeave.listen((_) { |
| 107 _leaveSubscription.cancel(); |
| 108 _leaveSubscription = null; |
| 109 _viewRoute = null; |
| 110 _cleanUp(); |
| 111 }); |
| 112 |
| 113 blockCache.fromUrl(templateUrl).then((blockFactory) { |
| 114 _cleanUp(); |
| 115 _previousScope = scope.$new(); |
| 116 _previousBlock = blockFactory( |
| 117 injector.createChild([new Module()..value(Scope, _previousScope)])); |
| 118 |
| 119 _previousBlock.elements.forEach((elm) => element.append(elm)); |
| 120 }); |
| 121 } |
| 122 |
| 123 _cleanUp() { |
| 124 if (_previousBlock == null) { |
| 125 return; |
| 126 } |
| 127 |
| 128 _previousBlock.remove(); |
| 129 _previousScope.$destroy(); |
| 130 |
| 131 _previousBlock = null; |
| 132 _previousScope = null; |
| 133 } |
| 134 |
| 135 Route get route => _viewRoute; |
| 136 String get routeName => _viewRoute.name; |
| 137 Map<String, String> get parameters { |
| 138 var res = <String, String>{}; |
| 139 var p = _viewRoute; |
| 140 while (p != null) { |
| 141 res.addAll(p.parameters); |
| 142 p = p.parent; |
| 143 } |
| 144 return res; |
| 145 } |
| 146 } |
| 147 |
| 148 |
| 149 /** |
| 150 * Class that can be injected to retrieve information about the current route. |
| 151 * For example: |
| 152 * |
| 153 * @NgComponent(/* ... */) |
| 154 * class MyComponent implement NgDetachAware { |
| 155 * RouteHandle route; |
| 156 * |
| 157 * MyComponent(RouteProvider routeProvider) { |
| 158 * _loadFoo(routeProvider.parameters['fooId']); |
| 159 * route = routeProvider.route.newHandle(); |
| 160 * route.onRoute.listen((RouteEvent e) { |
| 161 * // Do something when the route is activated. |
| 162 * }); |
| 163 * route.onLeave.listen((RouteEvent e) { |
| 164 * // Do something when the route is diactivated. |
| 165 * e.allowLeave(allDataSaved()); |
| 166 * }); |
| 167 * } |
| 168 * |
| 169 * detach() { |
| 170 * // The route handle must be discarded. |
| 171 * route.discard(); |
| 172 * } |
| 173 * |
| 174 * Future<bool> allDataSaved() { |
| 175 * // Check that all data is saved and confirm with the user if needed. |
| 176 * } |
| 177 * } |
| 178 * |
| 179 * If user component is used outside of ng-view directive then |
| 180 * injected [RouteProvider] will be null. |
| 181 */ |
| 182 abstract class RouteProvider { |
| 183 |
| 184 /** |
| 185 * Returns [Route] for current view. |
| 186 */ |
| 187 Route get route; |
| 188 |
| 189 /** |
| 190 * Returns the name of the current route. |
| 191 */ |
| 192 String get routeName; |
| 193 |
| 194 /** |
| 195 * Returns parameters for this route. |
| 196 */ |
| 197 Map<String, String> get parameters; |
| 198 } |
| OLD | NEW |