Skip to content

Commit 4563f72

Browse files
committed
refactor(routing): simplify the code, add comments
1 parent 5f20831 commit 4563f72

File tree

2 files changed

+75
-56
lines changed

2 files changed

+75
-56
lines changed

lib/routing/ng_view.dart

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -65,36 +65,38 @@ class NgView implements DetachAware, RouteProvider {
6565
final DirectiveInjector _dirInjector;
6666
final Element _element;
6767
final Scope _scope;
68-
RouteHandle _route;
68+
RouteHandle _parentRoute;
6969

7070
View _view;
7171
Scope _childScope;
7272
Route _viewRoute;
7373

74-
NgView(this._element, this._viewCache, DirectiveInjector dirInjector, this._appInjector,
75-
Router router, this._scope)
76-
: _dirInjector = dirInjector,
77-
_locationService = dirInjector.getByKey(NG_ROUTING_HELPER_KEY)
74+
NgView(this._element, this._viewCache, this._dirInjector, this._appInjector,
75+
Router router, this._scope, this._locationService)
7876
{
79-
RouteProvider routeProvider = dirInjector.getFromParentByKey(NG_VIEW_KEY);
80-
_route = routeProvider != null ?
77+
RouteProvider routeProvider = _dirInjector.getFromParentByKey(NG_VIEW_KEY);
78+
// Get the parent route
79+
// - from the parent `NgView` when it exists,
80+
// - from the router root otherwise.
81+
_parentRoute = routeProvider != null ?
8182
routeProvider.route.newHandle() :
8283
router.root.newHandle();
8384
_locationService._registerPortal(this);
8485
_maybeReloadViews();
8586
}
8687

88+
/// Reload the child views when the `_parentRoute` is active
8789
void _maybeReloadViews() {
88-
if (_route.isActive) _locationService._reloadViews(startingFrom: _route);
90+
if (_parentRoute.isActive) _locationService._reloadViews(startingFrom: _parentRoute);
8991
}
9092

9193
void detach() {
92-
_route.discard();
94+
_parentRoute.discard();
9395
_locationService._unregisterPortal(this);
9496
_cleanUp();
9597
}
9698

97-
void _show(_View viewDef, Route route, List<Module> modules) {
99+
void _show(_View viewDef, Route route) {
98100
assert(route.isActive);
99101

100102
if (_viewRoute != null) return;
@@ -110,14 +112,15 @@ class NgView implements DetachAware, RouteProvider {
110112

111113
Injector viewInjector = _appInjector;
112114

113-
if (modules != null) {
114-
viewInjector = createChildInjectorWithReload(_appInjector, modules);
115-
}
115+
List<Module> modules = viewDef.modules;
116+
if (modules != null) viewInjector = createChildInjectorWithReload(_appInjector, modules);
116117

117118
var newDirectives = viewInjector.getByKey(DIRECTIVE_MAP_KEY);
119+
118120
var viewFuture = viewDef.templateHtml != null ?
119121
new Future.value(_viewCache.fromHtml(viewDef.templateHtml, newDirectives)) :
120122
_viewCache.fromUrl(viewDef.template, newDirectives, Uri.base);
123+
121124
viewFuture.then((ViewFactory viewFactory) {
122125
_cleanUp();
123126
_childScope = _scope.createChild(new PrototypeMap(_scope.context));
@@ -135,19 +138,22 @@ class NgView implements DetachAware, RouteProvider {
135138
_childScope = null;
136139
}
137140

141+
/// implements `RouteProvider.route`
138142
Route get route => _viewRoute;
139143

144+
/// implements `RouteProvider.routeName`
140145
String get routeName => _viewRoute.name;
141146

147+
/// implements `RouteProvider.parameters`
142148
Map<String, String> get parameters {
143149
var res = new HashMap<String, String>();
144150
var p = _viewRoute;
145-
while (p != null) {
151+
for (Route p = _viewRoute; p != null; p = p.parent) {
146152
res.addAll(p.parameters);
147-
p = p.parent;
148153
}
149154
return res;
150155
}
156+
151157
/**
152158
* Creates a child injector that allows loading new directives, formatters and
153159
* services from the provided modules.

lib/routing/routing.dart

Lines changed: 54 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ class RouteViewFactory {
1313

1414
void _enterHandler(RouteEnterEvent event, String templateUrl,
1515
{List<Module> modules, String templateHtml}) {
16-
locationService._route(event.route, templateUrl, fromEvent: true,
17-
modules: modules, templateHtml: templateHtml);
16+
locationService._route(event.route, templateUrl, templateHtml, modules);
1817
}
1918

2019
void configure(Map<String, NgRouteCfg> config) {
@@ -32,8 +31,7 @@ class RouteViewFactory {
3231
dontLeaveOnParamChanges: cfg.dontLeaveOnParamChanges,
3332
enter: (RouteEnterEvent e) {
3433
if (cfg.view != null || cfg.viewHtml != null) {
35-
_enterHandler(e, cfg.view,
36-
modules: newModules, templateHtml: cfg.viewHtml);
34+
_enterHandler(e, cfg.view, modules: newModules, templateHtml: cfg.viewHtml);
3735
}
3836
if (cfg.enter != null) {
3937
cfg.enter(e);
@@ -56,11 +54,7 @@ class RouteViewFactory {
5654
cfg.preEnter(e);
5755
}
5856
},
59-
preLeave: (RoutePreLeaveEvent e) {
60-
if (cfg.preLeave != null) {
61-
cfg.preLeave(e);
62-
}
63-
},
57+
preLeave: cfg.preLeave,
6458
leave: cfg.leave,
6559
mount: (Route mountRoute) {
6660
if (cfg.mount != null) {
@@ -71,14 +65,31 @@ class RouteViewFactory {
7165
}
7266
}
7367

74-
NgRouteCfg ngRoute({String path, String view, String viewHtml,
75-
Map<String, NgRouteCfg> mount, modules(), bool defaultRoute: false,
76-
RoutePreEnterEventHandler preEnter, RouteEnterEventHandler enter,
77-
RoutePreLeaveEventHandler preLeave, RouteLeaveEventHandler leave,
78-
dontLeaveOnParamChanges: false}) =>
79-
new NgRouteCfg(path: path, view: view, viewHtml: viewHtml, mount: mount,
80-
modules: modules, defaultRoute: defaultRoute, preEnter: preEnter, preLeave: preLeave,
81-
enter: enter, leave: leave, dontLeaveOnParamChanges: dontLeaveOnParamChanges);
68+
/**
69+
* Helper function to create a route configuration (`NgRouteCfg`):
70+
* - `path`: url section (`/path`),
71+
* - `view`: external template,
72+
* - `viewHtml`: inline template,
73+
* - `mount`: child routes,
74+
* - `defaultRoute`: set to `true` for the default route,
75+
* - `*EventHandler`: event handlers, see route.dart for details,
76+
* - `dontLeaveOnParamChanges`: do not leave the route when only parameters change
77+
*/
78+
NgRouteCfg ngRoute({String path,
79+
String view,
80+
String viewHtml,
81+
Map<String, NgRouteCfg> mount,
82+
modules(),
83+
bool defaultRoute: false,
84+
RoutePreEnterEventHandler preEnter,
85+
RouteEnterEventHandler enter,
86+
RoutePreLeaveEventHandler preLeave,
87+
RouteLeaveEventHandler leave,
88+
dontLeaveOnParamChanges: false}) {
89+
return new NgRouteCfg(path: path, view: view, viewHtml: viewHtml, mount: mount, modules: modules,
90+
defaultRoute: defaultRoute, preEnter: preEnter, preLeave: preLeave, enter: enter,
91+
leave: leave, dontLeaveOnParamChanges: dontLeaveOnParamChanges);
92+
}
8293

8394
class NgRouteCfg {
8495
final String path;
@@ -125,12 +136,11 @@ typedef void RouteInitializerFn(Router router, RouteViewFactory viewFactory);
125136
@Injectable()
126137
class NgRoutingHelper {
127138
final Router router;
128-
final Application _ngApp;
129139
final _portals = <NgView>[];
130140
final _templates = <String, _View>{};
131141

132142
NgRoutingHelper(RouteInitializer initializer, Injector injector, this.router,
133-
this._ngApp) {
143+
Application ngApp) {
134144
// TODO: move this to constructor parameters when di issue is fixed:
135145
// https://github.com/angular/di.dart/issues/40
136146
RouteInitializerFn initializerFn = injector.getByKey(ROUTE_INITIALIZER_FN_KEY);
@@ -144,6 +154,8 @@ class NgRoutingHelper {
144154
} else {
145155
initializer.init(router, new RouteViewFactory(this));
146156
}
157+
158+
// Check if we need to update `ng-view`s when a new route is activated
147159
router.onRouteStart.listen((RouteStartEvent routeEvent) {
148160
routeEvent.completed.then((success) {
149161
if (success) {
@@ -152,34 +164,37 @@ class NgRoutingHelper {
152164
});
153165
});
154166

155-
router.listen(appRoot: _ngApp.element);
167+
// Make the router listen to URL change events and click events
168+
router.listen(appRoot: ngApp.element);
156169
}
157170

158171
void _reloadViews({Route startingFrom}) {
159-
var alreadyActiveViews = [];
160-
var activePath = router.activePath;
172+
var activeViews = <NgView>[];
173+
Iterable<Route> activePath = router.activePath;
161174
if (startingFrom != null) {
175+
// only consider child routes of the `startingFrom` route
162176
activePath = activePath.skip(_routeDepth(startingFrom));
163177
}
178+
164179
for (Route route in activePath) {
165-
var viewDef = _templates[_routePath(route)];
180+
var path = _routePath(route);
181+
var viewDef = _templates[path];
166182
if (viewDef == null) continue;
167-
var templateUrl = viewDef.template;
168-
169-
NgView view = _portals.lastWhere((NgView v) {
170-
return _routePath(route) != _routePath(v._route) &&
171-
_routePath(route).startsWith(_routePath(v._route));
172-
}, orElse: () => null);
173-
if (view != null && !alreadyActiveViews.contains(view)) {
174-
view._show(viewDef, route, viewDef.modules);
175-
alreadyActiveViews.add(view);
183+
184+
NgView view = _portals.lastWhere(
185+
(NgView v) => path != _routePath(v._parentRoute) &&
186+
path.startsWith(_routePath(v._parentRoute)),
187+
orElse: () => null);
188+
189+
if (view != null && !activeViews.contains(view)) {
190+
view._show(viewDef, route);
191+
activeViews.add(view);
176192
break;
177193
}
178194
}
179195
}
180196

181-
void _route(Route route, String template, {bool fromEvent, List<Module> modules,
182-
String templateHtml}) {
197+
void _route(Route route, String template, String templateHtml, List<Module> modules) {
183198
_templates[_routePath(route)] = new _View(template, templateHtml, modules);
184199
}
185200

@@ -200,22 +215,20 @@ class _View {
200215
_View(this.template, this.templateHtml, this.modules);
201216
}
202217

218+
/// Returns the route full path (ie `grand-parent.parent.current`)
203219
String _routePath(Route route) {
204-
final path = [];
205-
var p = route;
206-
while (p.parent != null) {
220+
final path = <String>[];
221+
for (Route p = route; p.parent != null; p = p.parent) {
207222
path.insert(0, p.name);
208-
p = p.parent;
209223
}
210224
return path.join('.');
211225
}
212226

227+
/// Returns the route depth (ie 3 for `grand-parent.parent.current`)
213228
int _routeDepth(Route route) {
214229
var depth = 0;
215-
var p = route;
216-
while (p.parent != null) {
230+
for (Route p = route; p.parent != null; p = p.parent) {
217231
depth++;
218-
p = p.parent;
219232
}
220233
return depth;
221234
}

0 commit comments

Comments
 (0)