fix(router): change router not to deactivate aux routes when navigating from a componentless routes

This commit is contained in:
vsavkin 2016-10-24 12:50:00 -07:00
parent 8f2fa0f766
commit 52a853e257
2 changed files with 48 additions and 19 deletions

View File

@ -921,9 +921,7 @@ class ActivateRoutes {
this.activateRoutes(c, prevChildren[c.value.outlet], outletMap); this.activateRoutes(c, prevChildren[c.value.outlet], outletMap);
delete prevChildren[c.value.outlet]; delete prevChildren[c.value.outlet];
}); });
forEach( forEach(prevChildren, (v: any, k: string) => this.deactiveRouteAndItsChildren(v, outletMap));
prevChildren,
(v: any, k: string) => this.deactivateOutletAndItChildren(outletMap._outlets[k]));
} }
activateRoutes( activateRoutes(
@ -939,7 +937,7 @@ class ActivateRoutes {
// If we have a normal route, we need to go through an outlet. // If we have a normal route, we need to go through an outlet.
if (future.component) { if (future.component) {
const outlet = getOutlet(parentOutletMap, futureNode.value); const outlet = getOutlet(parentOutletMap, future);
this.activateChildRoutes(futureNode, currNode, outlet.outletMap); this.activateChildRoutes(futureNode, currNode, outlet.outletMap);
// if we have a componentless route, we recurse but keep the same outlet map. // if we have a componentless route, we recurse but keep the same outlet map.
@ -948,15 +946,7 @@ class ActivateRoutes {
} }
} else { } else {
if (curr) { if (curr) {
// if we had a normal route, we need to deactivate only that outlet. this.deactiveRouteAndItsChildren(currNode, parentOutletMap);
if (curr.component) {
const outlet = getOutlet(parentOutletMap, futureNode.value);
this.deactivateOutletAndItChildren(outlet);
// if we had a componentless route, we need to deactivate everything!
} else {
this.deactivateOutletMap(parentOutletMap);
}
} }
// if we have a normal route, we need to advance the route // if we have a normal route, we need to advance the route
@ -998,16 +988,32 @@ class ActivateRoutes {
outletMap); outletMap);
} }
private deactivateOutletAndItChildren(outlet: RouterOutlet): void { private deactiveRouteAndItsChildren(
route: TreeNode<ActivatedRoute>, parentOutletMap: RouterOutletMap): void {
const prevChildren: {[key: string]: any} = nodeChildrenAsMap(route);
let outlet: RouterOutlet = null;
// getOutlet throws when cannot find the right outlet,
// which can happen if an outlet was in an NgIf and was removed
try {
outlet = getOutlet(parentOutletMap, route.value);
} catch (e) {
return;
}
const childOutletMap = outlet.outletMap;
forEach(prevChildren, (v: any, k: string) => {
if (route.value.component) {
this.deactiveRouteAndItsChildren(v, childOutletMap);
} else {
this.deactiveRouteAndItsChildren(v, parentOutletMap);
}
});
if (outlet && outlet.isActivated) { if (outlet && outlet.isActivated) {
this.deactivateOutletMap(outlet.outletMap);
outlet.deactivate(); outlet.deactivate();
} }
} }
private deactivateOutletMap(outletMap: RouterOutletMap): void {
forEach(outletMap._outlets, (v: RouterOutlet) => this.deactivateOutletAndItChildren(v));
}
} }
function parentLoadedConfig(snapshot: ActivatedRouteSnapshot): LoadedRouterConfig { function parentLoadedConfig(snapshot: ActivatedRouteSnapshot): LoadedRouterConfig {

View File

@ -531,6 +531,29 @@ describe('Integration', () => {
expect(fixture.nativeElement).toHaveText('primary [simple] right [user victor]'); expect(fixture.nativeElement).toHaveText('primary [simple] right [user victor]');
}))); })));
it('should not deactivate aux routes when navigating from a componentless routes',
fakeAsync(inject(
[Router, Location, NgModuleFactoryLoader],
(router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => {
const fixture = createRoot(router, TwoOutletsCmp);
router.resetConfig([
{path: 'simple', component: SimpleCmp},
{path: 'componentless', children: [{path: 'simple', component: SimpleCmp}]},
{path: 'user/:name', outlet: 'aux', component: UserCmp}
]);
router.navigateByUrl('/componentless/simple(aux:user/victor)');
advance(fixture);
expect(location.path()).toEqual('/componentless/simple(aux:user/victor)');
expect(fixture.nativeElement).toHaveText('[ simple, aux: user victor ]');
router.navigateByUrl('/simple(aux:user/victor)');
advance(fixture);
expect(location.path()).toEqual('/simple(aux:user/victor)');
expect(fixture.nativeElement).toHaveText('[ simple, aux: user victor ]');
})));
it('should emit an event when an outlet gets activated', fakeAsync(() => { it('should emit an event when an outlet gets activated', fakeAsync(() => {
@Component({ @Component({
selector: 'container', selector: 'container',