@@ -54,11 +54,16 @@ export class Router {
54
54
lastNavigationAttempt : string ;
55
55
56
56
private _currentInstruction : Instruction = null ;
57
+
57
58
private _currentNavigation : Promise < any > = _resolveToTrue ;
58
59
private _outlet : RouterOutlet = null ;
59
- private _auxOutlets : Map < string , RouterOutlet > = new Map ( ) ;
60
+
61
+ private _auxRouters : Map < string , Router > = new Map ( ) ;
62
+ private _childRouter : Router ;
63
+
60
64
private _subject : EventEmitter = new EventEmitter ( ) ;
61
65
66
+
62
67
constructor ( public registry : RouteRegistry , public _pipeline : Pipeline , public parent : Router ,
63
68
public hostComponent : any ) { }
64
69
@@ -67,26 +72,75 @@ export class Router {
67
72
* Constructs a child router. You probably don't need to use this unless you're writing a reusable
68
73
* component.
69
74
*/
70
- childRouter ( hostComponent : any ) : Router { return new ChildRouter ( this , hostComponent ) ; }
75
+ childRouter ( hostComponent : any ) : Router {
76
+ return this . _childRouter = new ChildRouter ( this , hostComponent ) ;
77
+ }
78
+
71
79
80
+ /**
81
+ * Constructs a child router. You probably don't need to use this unless you're writing a reusable
82
+ * component.
83
+ */
84
+ auxRouter ( hostComponent : any ) : Router { return new ChildRouter ( this , hostComponent ) ; }
72
85
73
86
/**
74
- * Register an object to notify of route changes. You probably don't need to use this unless
75
- * you're writing a reusable component.
87
+ * Register an outlet to notified of primary route changes.
88
+ *
89
+ * You probably don't need to use this unless you're writing a reusable component.
76
90
*/
77
- registerOutlet ( outlet : RouterOutlet ) : Promise < boolean > {
91
+ registerPrimaryOutlet ( outlet : RouterOutlet ) : Promise < boolean > {
78
92
if ( isPresent ( outlet . name ) ) {
79
- this . _auxOutlets . set ( outlet . name , outlet ) ;
80
- } else {
81
- this . _outlet = outlet ;
93
+ throw new BaseException ( `registerAuxOutlet expects to be called with an unnamed outlet.` ) ;
82
94
}
95
+
96
+ this . _outlet = outlet ;
83
97
if ( isPresent ( this . _currentInstruction ) ) {
84
- return outlet . commit ( this . _currentInstruction ) ;
98
+ return this . commit ( this . _currentInstruction , false ) ;
99
+ }
100
+ return _resolveToTrue ;
101
+ }
102
+
103
+ /**
104
+ * Register an outlet to notified of auxiliary route changes.
105
+ *
106
+ * You probably don't need to use this unless you're writing a reusable component.
107
+ */
108
+ registerAuxOutlet ( outlet : RouterOutlet ) : Promise < boolean > {
109
+ var outletName = outlet . name ;
110
+ if ( isBlank ( outletName ) ) {
111
+ throw new BaseException ( `registerAuxOutlet expects to be called with an outlet with a name.` ) ;
112
+ }
113
+
114
+ // TODO...
115
+ // what is the host of an aux route???
116
+ var router = this . auxRouter ( this . hostComponent ) ;
117
+
118
+ this . _auxRouters . set ( outletName , router ) ;
119
+ router . _outlet = outlet ;
120
+
121
+ var auxInstruction ;
122
+ if ( isPresent ( this . _currentInstruction ) &&
123
+ isPresent ( auxInstruction = this . _currentInstruction . auxInstruction [ outletName ] ) ) {
124
+ return router . commit ( auxInstruction ) ;
85
125
}
86
126
return _resolveToTrue ;
87
127
}
88
128
89
129
130
+ /**
131
+ * Given an instruction, returns `true` if the instruction is currently active,
132
+ * otherwise `false`.
133
+ */
134
+ isRouteActive ( instruction : Instruction ) : boolean {
135
+ var router = this ;
136
+ while ( isPresent ( router . parent ) && isPresent ( instruction . child ) ) {
137
+ router = router . parent ;
138
+ instruction = instruction . child ;
139
+ }
140
+ return isPresent ( this . _currentInstruction ) &&
141
+ this . _currentInstruction . component == instruction . component ;
142
+ }
143
+
90
144
/**
91
145
* Dynamically update the routing configuration and trigger a navigation.
92
146
*
@@ -143,7 +197,7 @@ export class Router {
143
197
144
198
_navigate ( instruction : Instruction , _skipLocationChange : boolean ) : Promise < any > {
145
199
return this . _settleInstruction ( instruction )
146
- . then ( ( _ ) => this . _reuse ( instruction ) )
200
+ . then ( ( _ ) => this . _canReuse ( instruction ) )
147
201
. then ( ( _ ) => this . _canActivate ( instruction ) )
148
202
. then ( ( result ) => {
149
203
if ( ! result ) {
@@ -190,14 +244,17 @@ export class Router {
190
244
} ) ;
191
245
}
192
246
193
- _reuse ( instruction : Instruction ) : Promise < any > {
247
+ /*
248
+ * Recursively set reuse flags
249
+ */
250
+ _canReuse ( instruction : Instruction ) : Promise < any > {
194
251
if ( isBlank ( this . _outlet ) ) {
195
252
return _resolveToFalse ;
196
253
}
197
- return this . _outlet . canReuse ( instruction )
254
+ return this . _outlet . canReuse ( instruction . component )
198
255
. then ( ( result ) => {
199
- if ( isPresent ( this . _outlet . childRouter ) && isPresent ( instruction . child ) ) {
200
- return this . _outlet . childRouter . _reuse ( instruction . child ) ;
256
+ if ( isPresent ( this . _childRouter ) && isPresent ( instruction . child ) ) {
257
+ return this . _childRouter . _canReuse ( instruction . child ) ;
201
258
}
202
259
} ) ;
203
260
}
@@ -211,19 +268,26 @@ export class Router {
211
268
return _resolveToTrue ;
212
269
}
213
270
var next : Promise < boolean > ;
214
- if ( isPresent ( instruction ) && instruction . component . reuse ) {
271
+ var childInstruction : Instruction = null ;
272
+ var reuse : boolean = false ;
273
+ var componentInstruction : ComponentInstruction = null ;
274
+ if ( isPresent ( instruction ) ) {
275
+ childInstruction = instruction . child ;
276
+ componentInstruction = instruction . component ;
277
+ reuse = instruction . component . reuse ;
278
+ }
279
+ if ( reuse ) {
215
280
next = _resolveToTrue ;
216
281
} else {
217
- next = this . _outlet . canDeactivate ( instruction ) ;
282
+ next = this . _outlet . canDeactivate ( componentInstruction ) ;
218
283
}
219
284
// TODO: aux route lifecycle hooks
220
285
return next . then ( ( result ) => {
221
286
if ( result == false ) {
222
287
return false ;
223
288
}
224
- if ( isPresent ( this . _outlet . childRouter ) ) {
225
- return this . _outlet . childRouter . _canDeactivate ( isPresent ( instruction ) ? instruction . child :
226
- null ) ;
289
+ if ( isPresent ( this . _childRouter ) ) {
290
+ return this . _childRouter . _canDeactivate ( childInstruction ) ;
227
291
}
228
292
return true ;
229
293
} ) ;
@@ -234,13 +298,29 @@ export class Router {
234
298
*/
235
299
commit ( instruction : Instruction , _skipLocationChange : boolean = false ) : Promise < any > {
236
300
this . _currentInstruction = instruction ;
237
- var next = _resolveToTrue ;
301
+ var next : Promise < any > = _resolveToTrue ;
238
302
if ( isPresent ( this . _outlet ) ) {
239
- next = this . _outlet . commit ( instruction ) ;
303
+ var componentInstruction = instruction . component ;
304
+ if ( componentInstruction . reuse ) {
305
+ next = this . _outlet . reuse ( componentInstruction ) ;
306
+ } else {
307
+ next =
308
+ this . deactivate ( instruction ) . then ( ( _ ) => this . _outlet . activate ( componentInstruction ) ) ;
309
+ }
310
+ if ( isPresent ( instruction . child ) ) {
311
+ next = next . then ( ( _ ) => {
312
+ if ( isPresent ( this . _childRouter ) ) {
313
+ return this . _childRouter . commit ( instruction . child ) ;
314
+ }
315
+ } ) ;
316
+ }
240
317
}
318
+
241
319
var promises = [ ] ;
242
- MapWrapper . forEach ( this . _auxOutlets ,
243
- ( outlet , _ ) => { promises . push ( outlet . commit ( instruction ) ) ; } ) ;
320
+ MapWrapper . forEach ( this . _auxRouters , ( router , name ) => {
321
+ promises . push ( router . commit ( instruction . auxInstruction [ name ] ) ) ;
322
+ } ) ;
323
+
244
324
return next . then ( ( _ ) => PromiseWrapper . all ( promises ) ) ;
245
325
}
246
326
@@ -262,10 +342,23 @@ export class Router {
262
342
* Removes the contents of this router's outlet and all descendant outlets
263
343
*/
264
344
deactivate ( instruction : Instruction ) : Promise < any > {
345
+ var childInstruction : Instruction = null ;
346
+ var componentInstruction : ComponentInstruction = null ;
347
+ if ( isPresent ( instruction ) ) {
348
+ childInstruction = instruction . child ;
349
+ componentInstruction = instruction . component ;
350
+ }
351
+ var next : Promise < any > = _resolveToTrue ;
352
+ if ( isPresent ( this . _childRouter ) ) {
353
+ next = this . _childRouter . deactivate ( childInstruction ) ;
354
+ }
265
355
if ( isPresent ( this . _outlet ) ) {
266
- return this . _outlet . deactivate ( instruction ) ;
356
+ next = next . then ( ( _ ) => this . _outlet . deactivate ( componentInstruction ) ) ;
267
357
}
268
- return _resolveToTrue ;
358
+
359
+ // TODO: handle aux routes
360
+
361
+ return next ;
269
362
}
270
363
271
364
0 commit comments