From 9d9e9c6ff1eb37d54a6e4af0a88f05a41f75d7a9 Mon Sep 17 00:00:00 2001 From: vsavkin Date: Wed, 27 Jul 2016 09:54:19 -0700 Subject: [PATCH] refactor(router): take advantage of the new way of configuring modules --- modules/@angular/router/index.ts | 2 +- .../router/src/common_router_providers.ts | 9 ++- .../router/src/directives/router_link.ts | 3 - modules/@angular/router/src/router_module.ts | 72 ++++++++++++------- modules/@angular/router/test/router.spec.ts | 24 +++---- .../router/testing/router_testing_module.ts | 3 +- .../playground/src/routing/app/inbox-app.ts | 10 ++- .../src/routing/app/inbox-detail.ts | 6 +- modules/playground/src/routing/index.ts | 9 ++- .../src/web_workers/router/index_common.ts | 4 +- tools/public_api_guard/router/index.d.ts | 12 ++-- 11 files changed, 83 insertions(+), 71 deletions(-) diff --git a/modules/@angular/router/index.ts b/modules/@angular/router/index.ts index a59d64b7c4..e8990c317a 100644 --- a/modules/@angular/router/index.ts +++ b/modules/@angular/router/index.ts @@ -14,7 +14,7 @@ export {RouterLinkActive} from './src/directives/router_link_active'; export {RouterOutlet} from './src/directives/router_outlet'; export {CanActivate, CanActivateChild, CanDeactivate, CanLoad, Resolve} from './src/interfaces'; export {Event, NavigationCancel, NavigationEnd, NavigationError, NavigationExtras, NavigationStart, Router, RoutesRecognized} from './src/router'; -export {ROUTER_DIRECTIVES, RouterModule, RouterModuleWithoutProviders} from './src/router_module'; +export {ROUTER_DIRECTIVES, RouterModule} from './src/router_module'; export {RouterOutletMap} from './src/router_outlet_map'; export {provideRouter} from './src/router_providers'; export {ActivatedRoute, ActivatedRouteSnapshot, RouterState, RouterStateSnapshot} from './src/router_state'; diff --git a/modules/@angular/router/src/common_router_providers.ts b/modules/@angular/router/src/common_router_providers.ts index 095e63a1e6..153b7ab664 100644 --- a/modules/@angular/router/src/common_router_providers.ts +++ b/modules/@angular/router/src/common_router_providers.ts @@ -21,7 +21,10 @@ export const ROUTER_CONFIGURATION = new OpaqueToken('ROUTER_CONFIGURATION'); /** * @experimental */ -export interface ExtraOptions { enableTracing?: boolean; } +export interface ExtraOptions { + enableTracing?: boolean; + useHash?: boolean; +} export function setupRouter( ref: ApplicationRef, resolver: ComponentResolver, urlSerializer: UrlSerializer, @@ -126,7 +129,7 @@ export function provideRouter(routes: Routes, config: ExtraOptions): any[] { * } * ``` * - * @experimental + * @deprecated */ export function provideRoutes(routes: Routes): any { return [ @@ -149,7 +152,7 @@ export function provideRoutes(routes: Routes): any { * } * ``` * - * @experimental + * @deprecated */ export function provideRouterConfig(config: ExtraOptions): any { return {provide: ROUTER_CONFIGURATION, useValue: config}; diff --git a/modules/@angular/router/src/directives/router_link.ts b/modules/@angular/router/src/directives/router_link.ts index 278130e872..742b4d2d18 100644 --- a/modules/@angular/router/src/directives/router_link.ts +++ b/modules/@angular/router/src/directives/router_link.ts @@ -130,9 +130,6 @@ export class RouterLinkWithHref implements OnChanges, OnDestroy { urlTree: UrlTree; - /** - * @internal - */ constructor( private router: Router, private route: ActivatedRoute, private locationStrategy: LocationStrategy) { diff --git a/modules/@angular/router/src/router_module.ts b/modules/@angular/router/src/router_module.ts index 10b288004b..03884d2ea9 100644 --- a/modules/@angular/router/src/router_module.ts +++ b/modules/@angular/router/src/router_module.ts @@ -6,10 +6,11 @@ * found in the LICENSE file at https://angular.io/license */ -import {Location, LocationStrategy, PathLocationStrategy} from '@angular/common'; -import {ApplicationRef, ComponentResolver, Injector, NgModule, NgModuleFactoryLoader, OpaqueToken, SystemJsNgModuleLoader} from '@angular/core'; +import {HashLocationStrategy, Location, LocationStrategy, PathLocationStrategy} from '@angular/common'; +import {ApplicationRef, ComponentResolver, Injector, ModuleWithProviders, NgModule, NgModuleFactoryLoader, OpaqueToken, SystemJsNgModuleLoader} from '@angular/core'; -import {ROUTER_CONFIGURATION, rootRoute, setupRouter} from './common_router_providers'; +import {ExtraOptions, ROUTER_CONFIGURATION, provideRouterConfig, provideRoutes, rootRoute, setupRouter} from './common_router_providers'; +import {Routes} from './config'; import {RouterLink, RouterLinkWithHref} from './directives/router_link'; import {RouterLinkActive} from './directives/router_link_active'; import {RouterOutlet} from './directives/router_outlet'; @@ -26,9 +27,17 @@ import {DefaultUrlSerializer, UrlSerializer} from './url_tree'; */ export const ROUTER_DIRECTIVES = [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive]; +const pathLocationStrategy = { + provide: LocationStrategy, + useClass: PathLocationStrategy +}; +const hashLocationStrategy = { + provide: LocationStrategy, + useClass: HashLocationStrategy +}; + export const ROUTER_PROVIDERS: any[] = [ - Location, {provide: LocationStrategy, useClass: PathLocationStrategy}, - {provide: UrlSerializer, useClass: DefaultUrlSerializer}, { + Location, {provide: UrlSerializer, useClass: DefaultUrlSerializer}, { provide: Router, useFactory: setupRouter, deps: [ @@ -41,41 +50,36 @@ export const ROUTER_PROVIDERS: any[] = [ {provide: ROUTER_CONFIGURATION, useValue: {enableTracing: false}} ]; - /** - * Router module to be used for lazy loaded parts. + * Router module. + * + * When registered at the root, it should be used as follows: + * + * ### Example + * + * ``` + * bootstrap(AppCmp, {imports: [RouterModule.forRoot(ROUTES)]}); + * ``` + * + * For lazy loaded modules it should be used as follows: * * ### Example * * ``` * @NgModule({ - * imports: [RouterModuleWithoutProviders] + * imports: [RouterModule.forChild(CHILD_ROUTES)] * }) - * class TeamsModule {} - * ``` - * - * @experimental We will soon have a way for the `RouterModule` to be imported with and without a - * provider, - * and then this module will be removed. - */ -@NgModule({declarations: ROUTER_DIRECTIVES, exports: ROUTER_DIRECTIVES}) -export class RouterModuleWithoutProviders { -} - -/** - * Router module. - * - * ### Example - * - * ``` - * bootstrap(AppCmp, {modules: [RouterModule]}); + * class Lazy {} * ``` * * @experimental */ -@NgModule({exports: [RouterModuleWithoutProviders], providers: ROUTER_PROVIDERS}) +@NgModule({declarations: ROUTER_DIRECTIVES, exports: ROUTER_DIRECTIVES}) export class RouterModule { constructor(private injector: Injector) { + // do the initialization only once + if ((injector).parent.get(RouterModule, null)) return; + setTimeout(() => { const appRef = injector.get(ApplicationRef); if (appRef.componentTypes.length == 0) { @@ -85,4 +89,18 @@ export class RouterModule { } }, 0); } + + static forRoot(routes: Routes, config?: ExtraOptions): ModuleWithProviders { + return { + ngModule: RouterModule, + providers: [ + ROUTER_PROVIDERS, provideRoutes(routes), config ? provideRouterConfig(config) : [], + config.useHash ? hashLocationStrategy : pathLocationStrategy + ] + }; + } + + static forChild(routes: Routes): ModuleWithProviders { + return {ngModule: RouterModule, providers: [provideRoutes(routes)]}; + } } diff --git a/modules/@angular/router/test/router.spec.ts b/modules/@angular/router/test/router.spec.ts index 57b343f5b2..073a560c66 100644 --- a/modules/@angular/router/test/router.spec.ts +++ b/modules/@angular/router/test/router.spec.ts @@ -15,7 +15,7 @@ import {expect} from '@angular/platform-browser/testing/matchers'; import {Observable} from 'rxjs/Observable'; import {of } from 'rxjs/observable/of'; -import {ActivatedRoute, ActivatedRouteSnapshot, CanActivate, CanDeactivate, Event, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, Params, ROUTER_DIRECTIVES, Resolve, Router, RouterModuleWithoutProviders, RouterStateSnapshot, RoutesRecognized, provideRoutes} from '../index'; +import {ActivatedRoute, ActivatedRouteSnapshot, CanActivate, CanDeactivate, Event, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, Params, ROUTER_DIRECTIVES, Resolve, Router, RouterModule, RouterStateSnapshot, RoutesRecognized, provideRoutes} from '../index'; import {RouterTestingModule, SpyNgModuleFactoryLoader} from '../testing'; describe('Integration', () => { @@ -1202,8 +1202,8 @@ describe('Integration', () => { @NgModule({ declarations: [LazyLoadedComponent], - providers: [provideRoutes([{path: 'loaded', component: LazyLoadedComponent}])], - imports: [RouterModuleWithoutProviders], + imports: + [RouterModule.forChild([{path: 'loaded', component: LazyLoadedComponent}])], entryComponents: [LazyLoadedComponent] }) class LoadedModule { @@ -1388,12 +1388,11 @@ describe('Integration', () => { @NgModule({ declarations: [ParentLazyLoadedComponent, ChildLazyLoadedComponent], - providers: [provideRoutes([{ + imports: [RouterModule.forChild([{ path: 'loaded', component: ParentLazyLoadedComponent, children: [{path: 'child', component: ChildLazyLoadedComponent}] }])], - imports: [RouterModuleWithoutProviders], entryComponents: [ParentLazyLoadedComponent, ChildLazyLoadedComponent] }) class LoadedModule { @@ -1429,15 +1428,12 @@ describe('Integration', () => { @NgModule({ entryComponents: [LazyLoadedComponent], declarations: [LazyLoadedComponent], - imports: [RouterModuleWithoutProviders], - providers: [ - LazyLoadedService, provideRoutes([{ - path: '', - canActivate: ['alwaysTrue'], - children: [{path: 'loaded', component: LazyLoadedComponent}] - }]), - {provide: 'alwaysTrue', useValue: () => true} - ] + imports: [RouterModule.forChild([{ + path: '', + canActivate: ['alwaysTrue'], + children: [{path: 'loaded', component: LazyLoadedComponent}] + }])], + providers: [LazyLoadedService, {provide: 'alwaysTrue', useValue: () => true}] }) class LoadedModule { } diff --git a/modules/@angular/router/testing/router_testing_module.ts b/modules/@angular/router/testing/router_testing_module.ts index fbc3e4847e..d06561cb59 100644 --- a/modules/@angular/router/testing/router_testing_module.ts +++ b/modules/@angular/router/testing/router_testing_module.ts @@ -12,7 +12,7 @@ import {Compiler, ComponentResolver, Injectable, Injector, NgModule, NgModuleFac import {Router, RouterOutletMap, Routes, UrlSerializer} from '../index'; import {ROUTES} from '../src/router_config_loader'; -import {RouterModule} from '../src/router_module'; +import {ROUTER_PROVIDERS, RouterModule} from '../src/router_module'; @@ -64,6 +64,7 @@ function setupTestingRouter( @NgModule({ exports: [RouterModule], providers: [ + ROUTER_PROVIDERS, {provide: Location, useClass: SpyLocation}, {provide: LocationStrategy, useClass: MockLocationStrategy}, {provide: NgModuleFactoryLoader, useClass: SpyNgModuleFactoryLoader}, diff --git a/modules/playground/src/routing/app/inbox-app.ts b/modules/playground/src/routing/app/inbox-app.ts index ba98bbc638..43998afe21 100644 --- a/modules/playground/src/routing/app/inbox-app.ts +++ b/modules/playground/src/routing/app/inbox-app.ts @@ -7,7 +7,7 @@ */ import {Component, Injectable} from '@angular/core'; -import {ROUTER_DIRECTIVES, ActivatedRoute, Router} from '@angular/router'; +import {ActivatedRoute, Router} from '@angular/router'; import * as db from './data'; import {Location} from '@angular/common'; import {PromiseWrapper, PromiseCompleter} from '@angular/core/src/facade/async'; @@ -89,7 +89,7 @@ export class DbService { } } -@Component({selector: 'inbox', templateUrl: 'app/inbox.html', directives: ROUTER_DIRECTIVES}) +@Component({selector: 'inbox', templateUrl: 'app/inbox.html'}) export class InboxCmp { private items: InboxRecord[] = []; private ready: boolean = false; @@ -116,7 +116,7 @@ export class InboxCmp { } -@Component({selector: 'drafts', templateUrl: 'app/drafts.html', directives: ROUTER_DIRECTIVES}) +@Component({selector: 'drafts', templateUrl: 'app/drafts.html'}) export class DraftsCmp { private items: InboxRecord[] = []; private ready: boolean = false; @@ -138,8 +138,6 @@ export const ROUTER_CONFIG = [ @Component({ selector: 'inbox-app', - viewProviders: [DbService], - templateUrl: 'app/inbox-app.html', - directives: ROUTER_DIRECTIVES + templateUrl: 'app/inbox-app.html' }) export class InboxApp {} diff --git a/modules/playground/src/routing/app/inbox-detail.ts b/modules/playground/src/routing/app/inbox-detail.ts index 551a8ceafc..29d3e65c19 100644 --- a/modules/playground/src/routing/app/inbox-detail.ts +++ b/modules/playground/src/routing/app/inbox-detail.ts @@ -7,12 +7,12 @@ */ import {Component, NgModule} from '@angular/core'; -import {ROUTER_DIRECTIVES, ActivatedRoute, provideRoutes} from '@angular/router'; +import {ActivatedRoute, RouterModule} from '@angular/router'; import {PromiseWrapper} from '@angular/core/src/facade/async'; import {InboxRecord, DbService} from './inbox-app'; @Component( - {selector: 'inbox-detail', directives: ROUTER_DIRECTIVES, templateUrl: 'app/inbox-detail.html'}) + {selector: 'inbox-detail', templateUrl: 'app/inbox-detail.html'}) export class InboxDetailCmp { private record: InboxRecord = new InboxRecord(); private ready: boolean = false; @@ -26,6 +26,6 @@ export class InboxDetailCmp { @NgModule({ declarations: [InboxDetailCmp], - providers: [provideRoutes([{path: ':id', component: InboxDetailCmp}])] + imports: [RouterModule.forChild([{path: ':id', component: InboxDetailCmp}])] }) export default class InboxDetailModule {} diff --git a/modules/playground/src/routing/index.ts b/modules/playground/src/routing/index.ts index 4b4d84a289..e628bd47db 100644 --- a/modules/playground/src/routing/index.ts +++ b/modules/playground/src/routing/index.ts @@ -6,18 +6,17 @@ * found in the LICENSE file at https://angular.io/license */ -import {InboxApp, InboxCmp, DraftsCmp, ROUTER_CONFIG} from './app/inbox-app'; +import {InboxApp, InboxCmp, DraftsCmp, DbService, ROUTER_CONFIG} from './app/inbox-app'; import {bootstrap} from '@angular/platform-browser-dynamic'; import {HashLocationStrategy, LocationStrategy} from '@angular/common'; -import {provideRoutes, RouterModule} from '@angular/router'; +import {RouterModule} from '@angular/router'; export function main() { bootstrap(InboxApp, { providers: [ - provideRoutes(ROUTER_CONFIG), - {provide: LocationStrategy, useClass: HashLocationStrategy} + DbService ], declarations: [InboxCmp, DraftsCmp], - imports: [RouterModule] + imports: [RouterModule.forRoot(ROUTER_CONFIG, {useHash: true})] }); } diff --git a/modules/playground/src/web_workers/router/index_common.ts b/modules/playground/src/web_workers/router/index_common.ts index c36ec31f26..2c1c5a8ae8 100644 --- a/modules/playground/src/web_workers/router/index_common.ts +++ b/modules/playground/src/web_workers/router/index_common.ts @@ -29,8 +29,8 @@ export const ROUTES = [ ]; @NgModule({ - imports: [WorkerAppModule, RouterModule], - providers: [provideRoutes(ROUTES), WORKER_APP_LOCATION_PROVIDERS, {provide: LocationStrategy, useClass: HashLocationStrategy}], + imports: [WorkerAppModule, RouterModule.forRoot(ROUTES, {useHash: true})], + providers: [WORKER_APP_LOCATION_PROVIDERS], entryComponents: [App], declarations: [App, Start, Contact, About] }) diff --git a/tools/public_api_guard/router/index.d.ts b/tools/public_api_guard/router/index.d.ts index 98ac22019b..7fc9a46ea4 100644 --- a/tools/public_api_guard/router/index.d.ts +++ b/tools/public_api_guard/router/index.d.ts @@ -56,6 +56,7 @@ export declare type Event = NavigationStart | NavigationEnd | NavigationCancel | /** @experimental */ export interface ExtraOptions { enableTracing?: boolean; + useHash?: boolean; } /** @stable */ @@ -112,10 +113,10 @@ export declare const PRIMARY_OUTLET: string; /** @experimental */ export declare function provideRouter(config: Routes, opts?: ExtraOptions): any[]; -/** @experimental */ +/** @deprecated */ export declare function provideRouterConfig(config: ExtraOptions): any; -/** @experimental */ +/** @deprecated */ export declare function provideRoutes(routes: Routes): any; /** @experimental */ @@ -198,6 +199,7 @@ export declare class RouterLinkWithHref implements OnChanges, OnDestroy { }; target: string; urlTree: UrlTree; + constructor(router: Router, route: ActivatedRoute, locationStrategy: LocationStrategy); ngOnChanges(changes: {}): any; ngOnDestroy(): any; onClick(button: number, ctrlKey: boolean, metaKey: boolean): boolean; @@ -206,10 +208,8 @@ export declare class RouterLinkWithHref implements OnChanges, OnDestroy { /** @experimental */ export declare class RouterModule { constructor(injector: Injector); -} - -/** @experimental */ -export declare class RouterModuleWithoutProviders { + static forChild(routes: Routes): ModuleWithProviders; + static forRoot(routes: Routes, config?: ExtraOptions): ModuleWithProviders; } /** @stable */