refactor(router): clean up naming

This commit is contained in:
vsavkin 2016-07-06 16:19:52 -07:00
parent 8aa2a0c1b2
commit 37e6da6dfb
18 changed files with 326 additions and 89 deletions

View File

@ -7,16 +7,16 @@
*/ */
export {ExtraOptions, provideRoutes, provideRouterConfig} from './src/common_router_providers'; export {ExtraOptions, provideRouterConfig, provideRoutes} from './src/common_router_providers';
export {Data, ResolveData, Route, RouterConfig} from './src/config'; export {Data, ResolveData, Route, RouterConfig, Routes} from './src/config';
export {RouterLink, RouterLinkWithHref} from './src/directives/router_link'; export {RouterLink, RouterLinkWithHref} from './src/directives/router_link';
export {RouterLinkActive} from './src/directives/router_link_active'; export {RouterLinkActive} from './src/directives/router_link_active';
export {RouterOutlet} from './src/directives/router_outlet'; export {RouterOutlet} from './src/directives/router_outlet';
export {CanActivate, CanDeactivate, Resolve} from './src/interfaces'; export {CanActivate, CanDeactivate, Resolve} from './src/interfaces';
export {Event, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, Router, RoutesRecognized} from './src/router'; export {Event, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, Router, RoutesRecognized} from './src/router';
export {ROUTER_DIRECTIVES, RouterAppModule} from './src/router_app_module';
export {RouterOutletMap} from './src/router_outlet_map'; export {RouterOutletMap} from './src/router_outlet_map';
export {provideRouter} from './src/router_providers'; export {provideRouter} from './src/router_providers';
export {ActivatedRoute, ActivatedRouteSnapshot, RouterState, RouterStateSnapshot} from './src/router_state'; export {ActivatedRoute, ActivatedRouteSnapshot, RouterState, RouterStateSnapshot} from './src/router_state';
export {PRIMARY_OUTLET, Params} from './src/shared'; export {PRIMARY_OUTLET, Params} from './src/shared';
export {RouterAppModule, ROUTER_DIRECTIVES} from './src/router_app_module';
export {DefaultUrlSerializer, UrlPathWithParams, UrlSerializer, UrlTree} from './src/url_tree'; export {DefaultUrlSerializer, UrlPathWithParams, UrlSerializer, UrlTree} from './src/url_tree';

View File

@ -15,7 +15,7 @@ import {Observer} from 'rxjs/Observer';
import {of } from 'rxjs/observable/of'; import {of } from 'rxjs/observable/of';
import {EmptyError} from 'rxjs/util/EmptyError'; import {EmptyError} from 'rxjs/util/EmptyError';
import {Route, RouterConfig} from './config'; import {Route, Routes} from './config';
import {RouterConfigLoader} from './router_config_loader'; import {RouterConfigLoader} from './router_config_loader';
import {PRIMARY_OUTLET} from './shared'; import {PRIMARY_OUTLET} from './shared';
import {UrlPathWithParams, UrlSegment, UrlTree} from './url_tree'; import {UrlPathWithParams, UrlSegment, UrlTree} from './url_tree';
@ -38,7 +38,7 @@ function absoluteRedirect(newPaths: UrlPathWithParams[]): Observable<UrlSegment>
} }
export function applyRedirects( export function applyRedirects(
configLoader: RouterConfigLoader, urlTree: UrlTree, config: RouterConfig): Observable<UrlTree> { configLoader: RouterConfigLoader, urlTree: UrlTree, config: Routes): Observable<UrlTree> {
return expandSegment(configLoader, config, urlTree.root, PRIMARY_OUTLET) return expandSegment(configLoader, config, urlTree.root, PRIMARY_OUTLET)
.map(rootSegment => createUrlTree(urlTree, rootSegment)) .map(rootSegment => createUrlTree(urlTree, rootSegment))
.catch(e => { .catch(e => {
@ -190,8 +190,8 @@ function matchPathsWithParamsAgainstRoute(
function getChildConfig(configLoader: RouterConfigLoader, route: Route): Observable<Route[]> { function getChildConfig(configLoader: RouterConfigLoader, route: Route): Observable<Route[]> {
if (route.children) { if (route.children) {
return of (route.children); return of (route.children);
} else if (route.mountChildren) { } else if (route.loadChildren) {
return configLoader.load(route.mountChildren).map(r => { return configLoader.load(route.loadChildren).map(r => {
(<any>route)._loadedConfig = r; (<any>route)._loadedConfig = r;
return r.routes; return r.routes;
}); });

View File

@ -9,14 +9,14 @@
import {Location, LocationStrategy, PathLocationStrategy} from '@angular/common'; import {Location, LocationStrategy, PathLocationStrategy} from '@angular/common';
import {APP_INITIALIZER, AppModuleFactoryLoader, ApplicationRef, ComponentResolver, Injector, OpaqueToken, SystemJsAppModuleLoader} from '@angular/core'; import {APP_INITIALIZER, AppModuleFactoryLoader, ApplicationRef, ComponentResolver, Injector, OpaqueToken, SystemJsAppModuleLoader} from '@angular/core';
import {RouterConfig} from './config'; import {Routes} from './config';
import {Router} from './router'; import {Router} from './router';
import {ROUTER_CONFIG} from './router_config_loader'; import {ROUTER_CONFIG, ROUTES} from './router_config_loader';
import {RouterOutletMap} from './router_outlet_map'; import {RouterOutletMap} from './router_outlet_map';
import {ActivatedRoute} from './router_state'; import {ActivatedRoute} from './router_state';
import {DefaultUrlSerializer, UrlSerializer} from './url_tree'; import {DefaultUrlSerializer, UrlSerializer} from './url_tree';
export const ROUTER_OPTIONS = new OpaqueToken('ROUTER_OPTIONS'); export const ROUTER_CONFIGURATION = new OpaqueToken('ROUTER_CONFIGURATION');
/** /**
* @experimental * @experimental
@ -26,7 +26,7 @@ export interface ExtraOptions { enableTracing?: boolean; }
export function setupRouter( export function setupRouter(
ref: ApplicationRef, resolver: ComponentResolver, urlSerializer: UrlSerializer, ref: ApplicationRef, resolver: ComponentResolver, urlSerializer: UrlSerializer,
outletMap: RouterOutletMap, location: Location, injector: Injector, outletMap: RouterOutletMap, location: Location, injector: Injector,
loader: AppModuleFactoryLoader, config: RouterConfig, opts: ExtraOptions) { loader: AppModuleFactoryLoader, config: Routes, opts: ExtraOptions) {
if (ref.componentTypes.length == 0) { if (ref.componentTypes.length == 0) {
throw new Error('Bootstrap at least one component before injecting Router.'); throw new Error('Bootstrap at least one component before injecting Router.');
} }
@ -82,10 +82,12 @@ export function setupRouterInitializer(injector: Injector) {
* *
* @deprecated use RouterAppModule instead * @deprecated use RouterAppModule instead
*/ */
export function provideRouter(_config: RouterConfig, _opts: ExtraOptions): any[] { export function provideRouter(routes: Routes, config: ExtraOptions): any[] {
return [ return [
{provide: ROUTER_CONFIG, useValue: _config}, {provide: ROUTER_OPTIONS, useValue: _opts}, {provide: ROUTES, useExisting: ROUTER_CONFIG}, {provide: ROUTER_CONFIG, useValue: routes},
Location, {provide: LocationStrategy, useClass: PathLocationStrategy},
{provide: ROUTER_CONFIGURATION, useValue: config}, Location,
{provide: LocationStrategy, useClass: PathLocationStrategy},
{provide: UrlSerializer, useClass: DefaultUrlSerializer}, {provide: UrlSerializer, useClass: DefaultUrlSerializer},
{ {
@ -93,7 +95,7 @@ export function provideRouter(_config: RouterConfig, _opts: ExtraOptions): any[]
useFactory: setupRouter, useFactory: setupRouter,
deps: [ deps: [
ApplicationRef, ComponentResolver, UrlSerializer, RouterOutletMap, Location, Injector, ApplicationRef, ComponentResolver, UrlSerializer, RouterOutletMap, Location, Injector,
AppModuleFactoryLoader, ROUTER_CONFIG, ROUTER_OPTIONS AppModuleFactoryLoader, ROUTES, ROUTER_CONFIGURATION
] ]
}, },
@ -122,8 +124,8 @@ export function provideRouter(_config: RouterConfig, _opts: ExtraOptions): any[]
* *
* @experimental * @experimental
*/ */
export function provideRoutes(config: RouterConfig): any { export function provideRoutes(routes: Routes): any {
return {provide: ROUTER_CONFIG, useValue: config}; return {provide: ROUTES, useValue: routes};
} }
/** /**
@ -142,6 +144,6 @@ export function provideRoutes(config: RouterConfig): any {
* *
* @experimental * @experimental
*/ */
export function provideRouterConfig(options: ExtraOptions): any { export function provideRouterConfig(config: ExtraOptions): any {
return {provide: ROUTER_OPTIONS, useValue: options}; return {provide: ROUTER_CONFIGURATION, useValue: config};
} }

View File

@ -8,8 +8,9 @@
import {Type} from '@angular/core'; import {Type} from '@angular/core';
/** /**
* `RouterConfig` is an array of route configurations. Each one has the following properties: * `Routes` is an array of route configurations. Each one has the following properties:
* *
* - *`path`* is a string that uses the route matcher DSL. * - *`path`* is a string that uses the route matcher DSL.
* - `pathMatch` is a string that specifies the matching strategy. * - `pathMatch` is a string that specifies the matching strategy.
@ -227,12 +228,235 @@ import {Type} from '@angular/core';
* With this configuration in place, navigating to '/parent/10' will create the main child and aux * With this configuration in place, navigating to '/parent/10' will create the main child and aux
* components. * components.
* *
* @stable * @deprecated use Routes
*/ */
export type RouterConfig = Route[]; export type RouterConfig = Route[];
/** /**
* See {@link RouterConfig} for more details. * `Routes` is an array of route configurations. Each one has the following properties:
*
* - *`path`* is a string that uses the route matcher DSL.
* - `pathMatch` is a string that specifies the matching strategy.
* - `component` is a component type.
* - `redirectTo` is the url fragment which will replace the current matched segment.
* - `outlet` is the name of the outlet the component should be placed into.
* - `canActivate` is an array of DI tokens used to look up CanActivate handlers. See {@link
* CanActivate} for more info.
* - `canDeactivate` is an array of DI tokens used to look up CanDeactivate handlers. See {@link
* CanDeactivate} for more info.
* - `data` is additional data provided to the component via `ActivatedRoute`.
* - `resolve` is a map of DI tokens used to look up data resolvers. See {@link Resolve} for more
* info.
* - `children` is an array of child route definitions.
*
* ### Simple Configuration
*
* ```
* [{
* path: 'team/:id',
* component: Team,
* children: [
* {
* path: 'user/:name',
* component: User
* }
* ]
* }]
* ```
*
* When navigating to `/team/11/user/bob`, the router will create the team component with the user
* component in it.
*
* ### Multiple Outlets
*
* ```
* [{
* path: 'team/:id',
* component: Team
* },
* {
* path: 'chat/:user',
* component: Chat
* outlet: aux
* }]
* ```
*
* When navigating to `/team/11(aux:chat/jim)`, the router will create the team component next to
* the chat component. The chat component will be placed into the aux outlet.
*
* ### Wild Cards
*
* ```
* [{
* path: '**',
* component: Sink
* }]
* ```
*
* Regardless of where you navigate to, the router will instantiate the sink component.
*
* ### Redirects
*
* ```
* [{
* path: 'team/:id',
* component: Team,
* children: [
* {
* path: 'legacy/user/:name',
* redirectTo: 'user/:name'
* },
* {
* path: 'user/:name',
* component: User
* }
* ]
* }]
* ```
*
* When navigating to '/team/11/legacy/user/jim', the router will change the url to
* '/team/11/user/jim', and then will instantiate the team component with the user component
* in it.
*
* If the `redirectTo` value starts with a '/', then it is an absolute redirect. E.g., if in the
* example above we change the `redirectTo` to `/user/:name`, the result url will be '/user/jim'.
*
* ### Empty Path
*
* Empty-path route configurations can be used to instantiate components that do not "consume"
* any url segments. Let's look at the following configuration:
*
* ```
* [{
* path: 'team/:id',
* component: Team,
* children: [
* {
* path: '',
* component: AllUsers
* },
* {
* path: 'user/:name',
* component: User
* }
* ]
* }]
* ```
*
* When navigating to `/team/11`, the router will instantiate the AllUsers component.
*
* Empty-path routes can have children.
*
* ```
* [{
* path: 'team/:id',
* component: Team,
* children: [
* {
* path: '',
* component: WrapperCmp,
* children: [
* {
* path: 'user/:name',
* component: User
* }
* ]
* }
* ]
* }]
* ```
*
* When navigating to `/team/11/user/jim`, the router will instantiate the wrapper component with
* the user component in it.
*
* ### Matching Strategy
*
* By default the router will look at what is left in the url, and check if it starts with
* the specified path (e.g., `/team/11/user` starts with `team/:id`).
*
* We can change the matching strategy to make sure that the path covers the whole unconsumed url,
* which is akin to `unconsumedUrl === path` or `$` regular expressions.
*
* This is particularly important when redirecting empty-path routes.
*
* ```
* [{
* path: '',
* pathMatch: 'prefix', //default
* redirectTo: 'main'
* },
* {
* path: 'main',
* component: Main
* }]
* ```
*
* Since an empty path is a prefix of any url, even when navigating to '/main', the router will
* still apply the redirect.
*
* If `pathMatch: full` is provided, the router will apply the redirect if and only if navigating to
* '/'.
*
* ```
* [{
* path: '',
* pathMatch: 'full',
* redirectTo: 'main'
* },
* {
* path: 'main',
* component: Main
* }]
* ```
*
* ### Componentless Routes
*
* It is useful at times to have the ability to share parameters between sibling components.
*
* Say we have two components--ChildCmp and AuxCmp--that we want to put next to each other and both
* of them require some id parameter.
*
* One way to do that would be to have a bogus parent component, so both the siblings can get the id
* parameter from it. This is not ideal. Instead, you can use a componentless route.
*
* ```
* [{
* path: 'parent/:id',
* children: [
* { path: 'a', component: MainChild },
* { path: 'b', component: AuxChild, outlet: 'aux' }
* ]
* }]
* ```
*
* So when navigating to `parent/10/(a//aux:b)`, the route will instantiate the main child and aux
* child components next to each other. In this example, the application component
* has to have the primary and aux outlets defined.
*
* The router will also merge the `params`, `data`, and `resolve` of the componentless parent into
* the `params`, `data`, and `resolve` of the children.
*
* This is especially useful when child components are defined as follows:
*
* ```
* [{
* path: 'parent/:id',
* children: [
* { path: '', component: MainChild },
* { path: '', component: AuxChild, outlet: 'aux' }
* ]
* }]
* ```
*
* With this configuration in place, navigating to '/parent/10' will create the main child and aux
* components.
*
* @stable use Routes
*/
export type Routes = Route[];
/**
* See {@link Routes} for more details.
* @stable * @stable
*/ */
export type Data = { export type Data = {
@ -240,7 +464,7 @@ export type Data = {
}; };
/** /**
* See {@link RouterConfig} for more details. * See {@link Routes} for more details.
* @stable * @stable
*/ */
export type ResolveData = { export type ResolveData = {
@ -248,7 +472,7 @@ export type ResolveData = {
}; };
/** /**
* See {@link RouterConfig} for more details. * See {@link Routes} for more details.
* @stable * @stable
*/ */
export interface Route { export interface Route {
@ -267,10 +491,10 @@ export interface Route {
data?: Data; data?: Data;
resolve?: ResolveData; resolve?: ResolveData;
children?: Route[]; children?: Route[];
mountChildren?: string; loadChildren?: string;
} }
export function validateConfig(config: RouterConfig): void { export function validateConfig(config: Routes): void {
config.forEach(validateNode); config.forEach(validateNode);
} }
@ -279,22 +503,22 @@ function validateNode(route: Route): void {
throw new Error( throw new Error(
`Invalid configuration of route '${route.path}': redirectTo and children cannot be used together`); `Invalid configuration of route '${route.path}': redirectTo and children cannot be used together`);
} }
if (!!route.redirectTo && !!route.mountChildren) { if (!!route.redirectTo && !!route.loadChildren) {
throw new Error( throw new Error(
`Invalid configuration of route '${route.path}': redirectTo and mountChildren cannot be used together`); `Invalid configuration of route '${route.path}': redirectTo and loadChildren cannot be used together`);
} }
if (!!route.children && !!route.mountChildren) { if (!!route.children && !!route.loadChildren) {
throw new Error( throw new Error(
`Invalid configuration of route '${route.path}': children and mountChildren cannot be used together`); `Invalid configuration of route '${route.path}': children and loadChildren cannot be used together`);
} }
if (!!route.redirectTo && !!route.component) { if (!!route.redirectTo && !!route.component) {
throw new Error( throw new Error(
`Invalid configuration of route '${route.path}': redirectTo and component cannot be used together`); `Invalid configuration of route '${route.path}': redirectTo and component cannot be used together`);
} }
if (route.redirectTo === undefined && !route.component && !route.children && if (route.redirectTo === undefined && !route.component && !route.children &&
!route.mountChildren) { !route.loadChildren) {
throw new Error( throw new Error(
`Invalid configuration of route '${route.path}': component, redirectTo, children, mountChildren must be provided`); `Invalid configuration of route '${route.path}': component, redirectTo, children, loadChildren must be provided`);
} }
if (route.path === undefined) { if (route.path === undefined) {
throw new Error(`Invalid route configuration: routes must have path specified`); throw new Error(`Invalid route configuration: routes must have path specified`);

View File

@ -79,7 +79,7 @@ export class RouterOutlet {
// const componentName = component ? component.name : null; // const componentName = component ? component.name : null;
// console.warn( // console.warn(
// `'${componentName}' not found in precompile array. To ensure all components referred // `'${componentName}' not found in precompile array. To ensure all components referred
// to by the RouterConfig are compiled, you must add '${componentName}' to the // to by the Routes are compiled, you must add '${componentName}' to the
// 'precompile' array of your application component. This will be required in a future // 'precompile' array of your application component. This will be required in a future
// release of the router.`); // release of the router.`);

View File

@ -11,7 +11,7 @@ import {Observable} from 'rxjs/Observable';
import {Observer} from 'rxjs/Observer'; import {Observer} from 'rxjs/Observer';
import {of } from 'rxjs/observable/of'; import {of } from 'rxjs/observable/of';
import {Data, ResolveData, Route, RouterConfig} from './config'; import {Data, ResolveData, Route, Routes} from './config';
import {ActivatedRouteSnapshot, InheritedResolve, RouterStateSnapshot} from './router_state'; import {ActivatedRouteSnapshot, InheritedResolve, RouterStateSnapshot} from './router_state';
import {PRIMARY_OUTLET, Params} from './shared'; import {PRIMARY_OUTLET, Params} from './shared';
import {UrlPathWithParams, UrlSegment, UrlTree, mapChildrenIntoArray} from './url_tree'; import {UrlPathWithParams, UrlSegment, UrlTree, mapChildrenIntoArray} from './url_tree';
@ -38,9 +38,8 @@ class InheritedFromParent {
} }
} }
export function recognize( export function recognize(rootComponentType: Type, config: Routes, urlTree: UrlTree, url: string):
rootComponentType: Type, config: RouterConfig, urlTree: UrlTree, Observable<RouterStateSnapshot> {
url: string): Observable<RouterStateSnapshot> {
try { try {
const children = const children =
processSegment(config, urlTree.root, InheritedFromParent.empty, PRIMARY_OUTLET); processSegment(config, urlTree.root, InheritedFromParent.empty, PRIMARY_OUTLET);
@ -152,7 +151,7 @@ function processPathsWithParamsAgainstRoute(
function getChildConfig(route: Route): Route[] { function getChildConfig(route: Route): Route[] {
if (route.children) { if (route.children) {
return route.children; return route.children;
} else if (route.mountChildren) { } else if (route.loadChildren) {
return (<any>route)._loadedConfig.routes; return (<any>route)._loadedConfig.routes;
} else { } else {
return []; return [];

View File

@ -22,7 +22,7 @@ import {Subscription} from 'rxjs/Subscription';
import {of } from 'rxjs/observable/of'; import {of } from 'rxjs/observable/of';
import {applyRedirects} from './apply_redirects'; import {applyRedirects} from './apply_redirects';
import {ResolveData, RouterConfig, validateConfig} from './config'; import {ResolveData, Routes, validateConfig} from './config';
import {createRouterState} from './create_router_state'; import {createRouterState} from './create_router_state';
import {createUrlTree} from './create_url_tree'; import {createUrlTree} from './create_url_tree';
import {RouterOutlet} from './directives/router_outlet'; import {RouterOutlet} from './directives/router_outlet';
@ -113,7 +113,7 @@ export type Event = NavigationStart | NavigationEnd | NavigationCancel | Navigat
/** /**
* The `Router` is responsible for mapping URLs to components. * The `Router` is responsible for mapping URLs to components.
* *
* See {@link RouterConfig) for more details and examples. * See {@link Routes) for more details and examples.
* *
* @stable * @stable
*/ */
@ -123,7 +123,7 @@ export class Router {
private locationSubscription: Subscription; private locationSubscription: Subscription;
private routerEvents: Subject<Event>; private routerEvents: Subject<Event>;
private navigationId: number = 0; private navigationId: number = 0;
private config: RouterConfig; private config: Routes;
private futureUrlTree: UrlTree; private futureUrlTree: UrlTree;
private configLoader: RouterConfigLoader; private configLoader: RouterConfigLoader;
@ -134,7 +134,7 @@ export class Router {
private rootComponentType: Type, private resolver: ComponentResolver, private rootComponentType: Type, private resolver: ComponentResolver,
private urlSerializer: UrlSerializer, private outletMap: RouterOutletMap, private urlSerializer: UrlSerializer, private outletMap: RouterOutletMap,
private location: Location, private injector: Injector, loader: AppModuleFactoryLoader, private location: Location, private injector: Injector, loader: AppModuleFactoryLoader,
config: RouterConfig) { config: Routes) {
this.resetConfig(config); this.resetConfig(config);
this.routerEvents = new Subject<Event>(); this.routerEvents = new Subject<Event>();
this.currentUrlTree = createEmptyUrlTree(); this.currentUrlTree = createEmptyUrlTree();
@ -180,7 +180,7 @@ export class Router {
* ]); * ]);
* ``` * ```
*/ */
resetConfig(config: RouterConfig): void { resetConfig(config: Routes): void {
validateConfig(config); validateConfig(config);
this.config = config; this.config = config;
} }

View File

@ -6,20 +6,19 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {AppModule} from '@angular/core';
import {Location, LocationStrategy, PathLocationStrategy} from '@angular/common'; import {Location, LocationStrategy, PathLocationStrategy} from '@angular/common';
import {APP_INITIALIZER, AppModuleFactoryLoader, ApplicationRef, ComponentResolver, Injector, OpaqueToken, SystemJsAppModuleLoader} from '@angular/core'; import {AppModule, AppModuleFactoryLoader, ApplicationRef, ComponentResolver, Injector, OpaqueToken, SystemJsAppModuleLoader} from '@angular/core';
import {ROUTER_CONFIGURATION, setupRouter} from './common_router_providers';
import {RouterLink, RouterLinkWithHref} from './directives/router_link';
import {RouterLinkActive} from './directives/router_link_active';
import {RouterOutlet} from './directives/router_outlet';
import {Router} from './router'; import {Router} from './router';
import {setupRouter, ROUTER_OPTIONS} from './common_router_providers'; import {ROUTES} from './router_config_loader';
import {ROUTER_CONFIG} from './router_config_loader';
import {RouterOutletMap} from './router_outlet_map'; import {RouterOutletMap} from './router_outlet_map';
import {ActivatedRoute} from './router_state'; import {ActivatedRoute} from './router_state';
import {DefaultUrlSerializer, UrlSerializer} from './url_tree'; import {DefaultUrlSerializer, UrlSerializer} from './url_tree';
import {RouterLink, RouterLinkWithHref} from './directives/router_link';
import {RouterLinkActive} from './directives/router_link_active';
import {RouterOutlet} from './directives/router_outlet';
/** /**
* @stable * @stable
@ -42,19 +41,18 @@ export const ROUTER_DIRECTIVES = [RouterOutlet, RouterLink, RouterLinkWithHref,
directives: ROUTER_DIRECTIVES, directives: ROUTER_DIRECTIVES,
providers: [ providers: [
Location, {provide: LocationStrategy, useClass: PathLocationStrategy}, Location, {provide: LocationStrategy, useClass: PathLocationStrategy},
{provide: UrlSerializer, useClass: DefaultUrlSerializer}, {provide: UrlSerializer, useClass: DefaultUrlSerializer}, {
{
provide: Router, provide: Router,
useFactory: setupRouter, useFactory: setupRouter,
deps: [ deps: [
ApplicationRef, ComponentResolver, UrlSerializer, RouterOutletMap, Location, Injector, ApplicationRef, ComponentResolver, UrlSerializer, RouterOutletMap, Location, Injector,
AppModuleFactoryLoader, ROUTER_CONFIG, ROUTER_OPTIONS AppModuleFactoryLoader, ROUTES, ROUTER_CONFIGURATION
] ]
}, },
RouterOutletMap, RouterOutletMap,
{provide: ActivatedRoute, useFactory: (r: Router) => r.routerState.root, deps: [Router]}, {provide: ActivatedRoute, useFactory: (r: Router) => r.routerState.root, deps: [Router]},
{provide: AppModuleFactoryLoader, useClass: SystemJsAppModuleLoader}, {provide: AppModuleFactoryLoader, useClass: SystemJsAppModuleLoader},
{provide: ROUTER_OPTIONS, useValue: {enableTracing: false}} {provide: ROUTER_CONFIGURATION, useValue: {enableTracing: false}}
] ]
}) })
export class RouterAppModule { export class RouterAppModule {

View File

@ -12,7 +12,11 @@ import {fromPromise} from 'rxjs/observable/fromPromise';
import {Route} from './config'; import {Route} from './config';
/**
* @deprecated use Routes
*/
export const ROUTER_CONFIG = new OpaqueToken('ROUTER_CONFIG'); export const ROUTER_CONFIG = new OpaqueToken('ROUTER_CONFIG');
export const ROUTES = new OpaqueToken('ROUTES');
export class LoadedRouterConfig { export class LoadedRouterConfig {
constructor(public routes: Route[], public factoryResolver: ComponentFactoryResolver) {} constructor(public routes: Route[], public factoryResolver: ComponentFactoryResolver) {}
@ -24,7 +28,7 @@ export class RouterConfigLoader {
load(path: string): Observable<LoadedRouterConfig> { load(path: string): Observable<LoadedRouterConfig> {
return fromPromise(this.loader.load(path).then(r => { return fromPromise(this.loader.load(path).then(r => {
const ref = r.create(); const ref = r.create();
return new LoadedRouterConfig(ref.injector.get(ROUTER_CONFIG), ref.componentFactoryResolver); return new LoadedRouterConfig(ref.injector.get(ROUTES), ref.componentFactoryResolver);
})); }));
} }
} }

View File

@ -10,7 +10,7 @@ import {PlatformLocation} from '@angular/common';
import {BrowserPlatformLocation} from '@angular/platform-browser'; import {BrowserPlatformLocation} from '@angular/platform-browser';
import {ExtraOptions, provideRouter as provideRouter_} from './common_router_providers'; import {ExtraOptions, provideRouter as provideRouter_} from './common_router_providers';
import {RouterConfig} from './config'; import {Routes} from './config';
/** /**
@ -33,7 +33,7 @@ import {RouterConfig} from './config';
* *
* @experimental * @experimental
*/ */
export function provideRouter(config: RouterConfig, opts: ExtraOptions = {}): any[] { export function provideRouter(config: Routes, opts: ExtraOptions = {}): any[] {
return [ return [
{provide: PlatformLocation, useClass: BrowserPlatformLocation}, ...provideRouter_(config, opts) {provide: PlatformLocation, useClass: BrowserPlatformLocation}, ...provideRouter_(config, opts)
]; ];

View File

@ -2,7 +2,7 @@ import {Observable} from 'rxjs/Observable';
import {of } from 'rxjs/observable/of'; import {of } from 'rxjs/observable/of';
import {applyRedirects} from '../src/apply_redirects'; import {applyRedirects} from '../src/apply_redirects';
import {RouterConfig} from '../src/config'; import {Routes} from '../src/config';
import {LoadedRouterConfig} from '../src/router_config_loader'; import {LoadedRouterConfig} from '../src/router_config_loader';
import {DefaultUrlSerializer, UrlSegment, UrlTree, equalPathsWithParams} from '../src/url_tree'; import {DefaultUrlSerializer, UrlSegment, UrlTree, equalPathsWithParams} from '../src/url_tree';
@ -136,7 +136,7 @@ describe('applyRedirects', () => {
const loadedConfig = const loadedConfig =
new LoadedRouterConfig([{path: 'b', component: ComponentB}], <any>'stubFactoryResolver'); new LoadedRouterConfig([{path: 'b', component: ComponentB}], <any>'stubFactoryResolver');
const loader = {load: (p: any) => of (loadedConfig)}; const loader = {load: (p: any) => of (loadedConfig)};
const config = [{path: 'a', component: ComponentA, mountChildren: 'children'}]; const config = [{path: 'a', component: ComponentA, loadChildren: 'children'}];
applyRedirects(<any>loader, tree('a/b'), config).forEach(r => { applyRedirects(<any>loader, tree('a/b'), config).forEach(r => {
compareTrees(r, tree('/a/b')); compareTrees(r, tree('/a/b'));
@ -148,7 +148,7 @@ describe('applyRedirects', () => {
const loader = { const loader = {
load: (p: any) => new Observable<any>((obs: any) => obs.error(new Error('Loading Error'))) load: (p: any) => new Observable<any>((obs: any) => obs.error(new Error('Loading Error')))
}; };
const config = [{path: 'a', component: ComponentA, mountChildren: 'children'}]; const config = [{path: 'a', component: ComponentA, loadChildren: 'children'}];
applyRedirects(<any>loader, tree('a/b'), config).subscribe(() => {}, (e) => { applyRedirects(<any>loader, tree('a/b'), config).subscribe(() => {}, (e) => {
expect(e.message).toEqual('Loading Error'); expect(e.message).toEqual('Loading Error');
@ -188,7 +188,7 @@ describe('applyRedirects', () => {
}); });
it('should redirect empty path route only when terminal', () => { it('should redirect empty path route only when terminal', () => {
const config: RouterConfig = [ const config: Routes = [
{ {
path: 'a', path: 'a',
component: ComponentA, component: ComponentA,
@ -315,7 +315,7 @@ describe('applyRedirects', () => {
}); });
it('should not create a new child (terminal)', () => { it('should not create a new child (terminal)', () => {
const config: RouterConfig = [{ const config: Routes = [{
path: 'a', path: 'a',
children: [ children: [
{path: 'b', component: ComponentB, children: [{path: 'd', component: ComponentB}]}, {path: 'b', component: ComponentB, children: [{path: 'd', component: ComponentB}]},
@ -338,7 +338,7 @@ describe('applyRedirects', () => {
}); });
}); });
function checkRedirect(config: RouterConfig, url: string, callback: any): void { function checkRedirect(config: Routes, url: string, callback: any): void {
applyRedirects(null, tree(url), config).subscribe(callback, e => { throw e; }); applyRedirects(null, tree(url), config).subscribe(callback, e => { throw e; });
} }

View File

@ -15,16 +15,16 @@ describe('config', () => {
`Invalid configuration of route 'a': redirectTo and children cannot be used together`); `Invalid configuration of route 'a': redirectTo and children cannot be used together`);
}); });
it('should throw when redirectTo and mountChildren are used together', () => { it('should throw when redirectTo and loadChildren are used together', () => {
expect(() => { validateConfig([{path: 'a', redirectTo: 'b', mountChildren: 'value'}]); }) expect(() => { validateConfig([{path: 'a', redirectTo: 'b', loadChildren: 'value'}]); })
.toThrowError( .toThrowError(
`Invalid configuration of route 'a': redirectTo and mountChildren cannot be used together`); `Invalid configuration of route 'a': redirectTo and loadChildren cannot be used together`);
}); });
it('should throw when children and mountChildren are used together', () => { it('should throw when children and loadChildren are used together', () => {
expect(() => { validateConfig([{path: 'a', children: [], mountChildren: 'value'}]); }) expect(() => { validateConfig([{path: 'a', children: [], loadChildren: 'value'}]); })
.toThrowError( .toThrowError(
`Invalid configuration of route 'a': children and mountChildren cannot be used together`); `Invalid configuration of route 'a': children and loadChildren cannot be used together`);
}); });
it('should throw when component and redirectTo are used together', () => { it('should throw when component and redirectTo are used together', () => {
@ -42,7 +42,7 @@ describe('config', () => {
it('should throw when none of component and children or direct are missing', () => { it('should throw when none of component and children or direct are missing', () => {
expect(() => { validateConfig([{path: 'a'}]); }) expect(() => { validateConfig([{path: 'a'}]); })
.toThrowError( .toThrowError(
`Invalid configuration of route 'a': component, redirectTo, children, mountChildren must be provided`); `Invalid configuration of route 'a': component, redirectTo, children, loadChildren must be provided`);
}); });
it('should throw when path starts with a slash', () => { it('should throw when path starts with a slash', () => {

View File

@ -1,4 +1,4 @@
import {RouterConfig} from '../src/config'; import {Routes} from '../src/config';
import {createRouterState} from '../src/create_router_state'; import {createRouterState} from '../src/create_router_state';
import {recognize} from '../src/recognize'; import {recognize} from '../src/recognize';
import {ActivatedRoute, RouterState, RouterStateSnapshot, advanceActivatedRoute, createEmptyState} from '../src/router_state'; import {ActivatedRoute, RouterState, RouterStateSnapshot, advanceActivatedRoute, createEmptyState} from '../src/router_state';
@ -84,7 +84,7 @@ function advanceNode(node: TreeNode<ActivatedRoute>): void {
node.children.forEach(advanceNode); node.children.forEach(advanceNode);
} }
function createState(config: RouterConfig, url: string): RouterStateSnapshot { function createState(config: Routes, url: string): RouterStateSnapshot {
let res: RouterStateSnapshot; let res: RouterStateSnapshot;
recognize(RootComponent, config, tree(url), url).forEach(s => res = s); recognize(RootComponent, config, tree(url), url).forEach(s => res = s);
return res; return res;

View File

@ -1,4 +1,4 @@
import {RouterConfig} from '../src/config'; import {Routes} from '../src/config';
import {recognize} from '../src/recognize'; import {recognize} from '../src/recognize';
import {ActivatedRouteSnapshot, RouterStateSnapshot} from '../src/router_state'; import {ActivatedRouteSnapshot, RouterStateSnapshot} from '../src/router_state';
import {PRIMARY_OUTLET, Params} from '../src/shared'; import {PRIMARY_OUTLET, Params} from '../src/shared';
@ -529,7 +529,7 @@ describe('recognize', () => {
}); });
}); });
function checkRecognize(config: RouterConfig, url: string, callback: any): void { function checkRecognize(config: Routes, url: string, callback: any): void {
recognize(RootComponent, config, tree(url), url).subscribe(callback, e => { throw e; }); recognize(RootComponent, config, tree(url), url).subscribe(callback, e => { throw e; });
} }

View File

@ -1,4 +1,4 @@
import {RouterConfig} from '../src/config'; import {Routes} from '../src/config';
import {recognize} from '../src/recognize'; import {recognize} from '../src/recognize';
import {resolve} from '../src/resolve'; import {resolve} from '../src/resolve';
import {RouterStateSnapshot} from '../src/router_state'; import {RouterStateSnapshot} from '../src/router_state';
@ -22,7 +22,7 @@ describe('resolve', () => {
}); });
function checkResolve( function checkResolve(
config: RouterConfig, url: string, resolved: {[k: string]: string}, callback: any): void { config: Routes, url: string, resolved: {[k: string]: string}, callback: any): void {
const resolver = { const resolver = {
resolveComponent: (component: string): Promise<any> => { resolveComponent: (component: string): Promise<any> => {
if (resolved[component]) { if (resolved[component]) {

View File

@ -11,13 +11,12 @@ import {expect} from '@angular/platform-browser/testing/matchers';
import {Observable} from 'rxjs/Observable'; import {Observable} from 'rxjs/Observable';
import {of } from 'rxjs/observable/of'; import {of } from 'rxjs/observable/of';
import {ActivatedRoute, ActivatedRouteSnapshot, CanActivate, CanDeactivate, DefaultUrlSerializer, Event, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, Params, ROUTER_DIRECTIVES, Resolve, Router, RouterConfig, RouterOutletMap, RouterStateSnapshot, RoutesRecognized, UrlSerializer, provideRoutes} from '../index'; import {ActivatedRoute, ActivatedRouteSnapshot, CanActivate, CanDeactivate, DefaultUrlSerializer, Event, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, Params, ROUTER_DIRECTIVES, Resolve, Router, RouterOutletMap, RouterStateSnapshot, Routes, RoutesRecognized, UrlSerializer, provideRoutes} from '../index';
describe('Integration', () => { describe('Integration', () => {
beforeEachProviders(() => { beforeEachProviders(() => {
let config: RouterConfig = let config: Routes = [{path: '', component: BlankCmp}, {path: 'simple', component: SimpleCmp}];
[{path: '', component: BlankCmp}, {path: 'simple', component: SimpleCmp}];
return [ return [
RouterOutletMap, RouterOutletMap,
@ -1124,7 +1123,7 @@ describe('Integration', () => {
const fixture = createRoot(tcb, router, RootCmp); const fixture = createRoot(tcb, router, RootCmp);
router.resetConfig([{path: 'lazy', mountChildren: 'expected'}]); router.resetConfig([{path: 'lazy', loadChildren: 'expected'}]);
router.navigateByUrl('/lazy/loaded/child'); router.navigateByUrl('/lazy/loaded/child');
advance(fixture); advance(fixture);
@ -1142,7 +1141,7 @@ describe('Integration', () => {
(<any>loader).expectedPath = 'expected'; (<any>loader).expectedPath = 'expected';
const fixture = createRoot(tcb, router, RootCmp); const fixture = createRoot(tcb, router, RootCmp);
router.resetConfig([{path: 'lazy', mountChildren: 'invalid'}]); router.resetConfig([{path: 'lazy', loadChildren: 'invalid'}]);
const recordedEvents: any = []; const recordedEvents: any = [];
router.events.forEach(e => recordedEvents.push(e)); router.events.forEach(e => recordedEvents.push(e));

View File

@ -133,7 +133,7 @@ export const ROUTER_CONFIG = [
{path: '', terminal: true, redirectTo: 'inbox'}, {path: '', terminal: true, redirectTo: 'inbox'},
{path: 'inbox', component: InboxCmp}, {path: 'inbox', component: InboxCmp},
{path: 'drafts', component: DraftsCmp}, {path: 'drafts', component: DraftsCmp},
{path: 'detail', mountChildren: 'app/inbox-detail.js' } {path: 'detail', loadChildren: 'app/inbox-detail.js' }
]; ];
@Component({ @Component({

View File

@ -91,10 +91,13 @@ export declare type Params = {
export declare const PRIMARY_OUTLET: string; export declare const PRIMARY_OUTLET: string;
/** @experimental */ /** @experimental */
export declare function provideRouter(config: RouterConfig, opts?: ExtraOptions): any[]; export declare function provideRouter(config: Routes, opts?: ExtraOptions): any[];
/** @experimental */ /** @experimental */
export declare function provideRoutes(config: RouterConfig): any; export declare function provideRouterConfig(config: ExtraOptions): any;
/** @experimental */
export declare function provideRoutes(routes: Routes): any;
/** @experimental */ /** @experimental */
export interface Resolve<T> { export interface Resolve<T> {
@ -117,19 +120,24 @@ export declare class Router {
events: Observable<Event>; events: Observable<Event>;
routerState: RouterState; routerState: RouterState;
url: string; url: string;
constructor(rootComponentType: Type, resolver: ComponentResolver, urlSerializer: UrlSerializer, outletMap: RouterOutletMap, location: Location, injector: Injector, loader: AppModuleFactoryLoader, config: RouterConfig); constructor(rootComponentType: Type, resolver: ComponentResolver, urlSerializer: UrlSerializer, outletMap: RouterOutletMap, location: Location, injector: Injector, loader: AppModuleFactoryLoader, config: Routes);
createUrlTree(commands: any[], {relativeTo, queryParams, fragment}?: NavigationExtras): UrlTree; createUrlTree(commands: any[], {relativeTo, queryParams, fragment}?: NavigationExtras): UrlTree;
navigate(commands: any[], extras?: NavigationExtras): Promise<boolean>; navigate(commands: any[], extras?: NavigationExtras): Promise<boolean>;
navigateByUrl(url: string | UrlTree): Promise<boolean>; navigateByUrl(url: string | UrlTree): Promise<boolean>;
parseUrl(url: string): UrlTree; parseUrl(url: string): UrlTree;
resetConfig(config: RouterConfig): void; resetConfig(config: Routes): void;
serializeUrl(url: UrlTree): string; serializeUrl(url: UrlTree): string;
} }
/** @stable */ /** @stable */
export declare const ROUTER_DIRECTIVES: (typeof RouterOutlet | typeof RouterLink | typeof RouterLinkWithHref | typeof RouterLinkActive)[]; export declare const ROUTER_DIRECTIVES: (typeof RouterOutlet | typeof RouterLink | typeof RouterLinkWithHref | typeof RouterLinkActive)[];
/** @stable */ /** @experimental */
export declare class RouterAppModule {
constructor(injector: Injector);
}
/** @deprecated */
export declare type RouterConfig = Route[]; export declare type RouterConfig = Route[];
/** @stable */ /** @stable */
@ -202,6 +210,9 @@ export declare class RouterStateSnapshot extends Tree<ActivatedRouteSnapshot> {
toString(): string; toString(): string;
} }
/** @stable */
export declare type Routes = Route[];
/** @stable */ /** @stable */
export declare class RoutesRecognized { export declare class RoutesRecognized {
id: number; id: number;