Skip to content

Commit

Permalink
feat(ng2): Improve ng2 bootstrap flexibility with provideUIRouter() p…
Browse files Browse the repository at this point in the history
…rovider factory function

fix(ng2): Update deps to rc.6
Closes #2958
  • Loading branch information
christopherthielen committed Sep 4, 2016
1 parent c9b6570 commit bc17066
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 33 deletions.
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ui-router",
"description": "State-based routing for Javascript",
"version": "1.0.0-beta.1",
"version": "1.0.0-beta.2",
"scripts": {
"test": "npm run test:integrate",
"watch": "node_modules/watch/cli.js 'npm run test' src test",
Expand Down Expand Up @@ -56,11 +56,11 @@
},
"license": "MIT",
"devDependencies": {
"@angular/common": "=2.0.0-rc.5",
"@angular/compiler": "=2.0.0-rc.5",
"@angular/core": "=2.0.0-rc.5",
"@angular/platform-browser": "=2.0.0-rc.5",
"@angular/platform-browser-dynamic": "=2.0.0-rc.5",
"@angular/common": "=2.0.0-rc.6",
"@angular/compiler": "=2.0.0-rc.6",
"@angular/core": "=2.0.0-rc.6",
"@angular/platform-browser": "=2.0.0-rc.6",
"@angular/platform-browser-dynamic": "=2.0.0-rc.6",
"babel-core": "^5.8.14",
"clone": "^1.0.2",
"conventional-changelog": "^1.1.0",
Expand All @@ -82,7 +82,7 @@
"phantomjs-polyfill": "0.0.1",
"reflect-metadata": "=0.1.2",
"remap-istanbul": "^0.6.3",
"rxjs": "=5.0.0-beta.6",
"rxjs": "^5.0.0-beta.11",
"shelljs": "^0.7.0",
"systemjs": "^0.18.4",
"ts-loader": "^0.8.1",
Expand All @@ -94,6 +94,6 @@
"webpack": "1.x",
"webpack-dev-server": "1.x",
"yargs": "^4.2.0",
"zone.js": "=0.6.12"
"zone.js": "^0.6.17"
}
}
2 changes: 1 addition & 1 deletion packages/ng2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "ui-router-ng2",
"description": "State-based routing for Angular 2",
"peerDependencies": {
"@angular/core": "^2.0.0-rc.5"
"@angular/core": "^2.0.0-rc.6"
},
"main": "ng2.js",
"typings": "ng2.d.ts"
Expand Down
2 changes: 1 addition & 1 deletion src/ng2/directives/uiView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ interface InputMapping {
declare var Reflect: any;

/** @hidden */
const ng2ComponentInputs = (ng2CompClass: Type) => {
const ng2ComponentInputs = (ng2CompClass: Type<any>) => {
/** Get "@Input('foo') _foo" inputs */
let props = Reflect['getMetadata']('propMetadata', ng2CompClass);
let _props = Object.keys(props || {})
Expand Down
2 changes: 1 addition & 1 deletion src/ng2/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ export interface Ng2ViewDeclaration extends _ViewDeclaration {
* }
* ```
*/
component?: Type;
component?: Type<any>;

/**
* An object which maps `resolve` keys to [[component]] `bindings`.
Expand Down
4 changes: 2 additions & 2 deletions src/ng2/location.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** @module ng2 */ /** */
import {HashLocationStrategy, PlatformLocation, LocationStrategy, UrlChangeListener} from "@angular/common";
import {HashLocationStrategy, PlatformLocation, LocationStrategy, LocationChangeListener} from "@angular/common";
import {Injectable} from "@angular/core";

import {services} from "../common/coreservices";
Expand Down Expand Up @@ -60,7 +60,7 @@ export class UIRouterLocation {
console.log(new Error('$location.replace() not impl'))
};

loc.onChange = (cb: UrlChangeListener) => locSt.onPopState(cb);
loc.onChange = (cb: LocationChangeListener) => locSt.onPopState(cb);

let locCfg = <any> services.locationConfig;

Expand Down
53 changes: 45 additions & 8 deletions src/ng2/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
*
* @preferred @module ng2
*/ /** */
import {Injector, OpaqueToken} from "@angular/core";
import {Injector, OpaqueToken, Provider} from "@angular/core";
import {ClassProvider, ExistingProvider, FactoryProvider, TypeProvider, ValueProvider} from "@angular/core"; // has or is using
import {UIRouter} from "../router";
import {PathNode} from "../path/node";
import {StateRegistry} from "../state/stateRegistry";
Expand All @@ -62,17 +63,20 @@ import {UIRouterConfig} from "./uiRouterConfig";
import {Globals} from "../globals";
import {UIRouterLocation} from "./location";
import {services} from "../common/coreservices";
import {ProviderLike} from "../state/interface";
import {Resolvable} from "../resolve/resolvable";
import {ngModuleResolvablesBuilder} from "./statebuilders/lazyLoadNgModuleResolvable";
import {flattenR} from "../common/common";
import {UIROUTER_STATES_TOKEN} from "./uiRouterNgModule";
import {UIRouterRx} from "./rx";
import {LocationStrategy, HashLocationStrategy, PathLocationStrategy} from "@angular/common";

export const NG1_UIROUTER_TOKEN = new OpaqueToken("$uiRouter");

/**
* This is a provider factory for a UIRouter instance which is configured for Angular 2
* This is a factory function for a UIRouter instance
*
* Creates a UIRouter instance and configures it for Angular 2, then invokes router bootstrap.
* This function is used as an Angular 2 `useFactory` Provider.
*/
let uiRouterFactory = (injector: Injector) => {
// ----------------- ng1-to-ng2 short circuit ------
Expand Down Expand Up @@ -140,10 +144,12 @@ let uiRouterFactory = (injector: Injector) => {
return router;
};

export const _UIROUTER_PROVIDERS: ProviderLike[] = [
{ provide: UIRouterLocation, useClass: UIRouterLocation },
export const _UIROUTER_INSTANCE_PROVIDERS: Provider[] = [
{ provide: UIRouter, useFactory: uiRouterFactory, deps: [Injector] },
{ provide: UIRouterLocation, useClass: UIRouterLocation },
];

export const _UIROUTER_PROVIDERS: Provider[] = [
{ provide: StateService, useFactory: (r: UIRouter) => r.stateService , deps: [UIRouter]},
{ provide: TransitionService, useFactory: (r: UIRouter) => r.transitionService, deps: [UIRouter]},
{ provide: UrlMatcherFactory, useFactory: (r: UIRouter) => r.urlMatcherFactory, deps: [UIRouter]},
Expand All @@ -153,10 +159,41 @@ export const _UIROUTER_PROVIDERS: ProviderLike[] = [
{ provide: Globals, useFactory: (r: UIRouter) => r.globals , deps: [UIRouter]},

{ provide: UIView.PARENT_INJECT, useFactory: (r: StateRegistry) => { return { fqn: null, context: r.root() } as ParentUIViewInject }, deps: [StateRegistry]}
]
];

/**
* Provides an Instance of UI-Router for NG2.
*
* Use this on the root NgModule to configure and create an instance of the Angular 2 UIRouter.
*
* @example
* ```js
*
* @UIRouterModule({
* states: [ homeState, aboutState ],
* providers: [ provideUIRouter({ configClass: MyUIRouterConfig, useHash: true }) ],
* bootstrap: [ UIView ]
* }) class RootNgModule {}
*
* platformBrowserDynamic().bootstrapModule(RootNgModule);
* ```
*
* Note: UIRouter should only be provided *once*, on the root module, when bootstrapping the application.
*/
export function provideUIRouter(rootConfig: { configClass?: typeof UIRouterConfig, useHash?: boolean } = {}) {
// Provide the UIRouter instance providers
return _UIROUTER_INSTANCE_PROVIDERS.concat(
// Provide the user-supplied UIRouterConfig class, or use base UIRouterConfig (as a no-op config)
{ provide: UIRouterConfig, useClass: (rootConfig.configClass as any || UIRouterConfig) },
// Provide the PathLocationStrategy by default unless `useHash` is `true`
{ provide: LocationStrategy, useClass: (rootConfig.useHash ? HashLocationStrategy : PathLocationStrategy ) }
);
}

/**
* The UI-Router providers, for use in your application bootstrap
*
* @deprecated use [[UIRouterModule]]
* @deprecated use [[UIRouterModule]] and [[provideUIRouter]]
*/
export const UIROUTER_PROVIDERS = _UIROUTER_PROVIDERS;
export const UIROUTER_PROVIDERS: Provider[] = _UIROUTER_INSTANCE_PROVIDERS.concat(_UIROUTER_PROVIDERS);

38 changes: 26 additions & 12 deletions src/ng2/uiRouterNgModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {uniqR, flattenR} from "../common/common";
entryComponents: [UIView],
providers: [_UIROUTER_PROVIDERS]
})
export class UIRouterRootModule {}
export class UIRouterLibraryModule {}

/**
* A module declaration lteral, including UI-Router states.
Expand All @@ -28,11 +28,23 @@ export const UIROUTER_STATES_TOKEN = new OpaqueToken("UIRouter States");
/**
* Declares a NgModule with UI-Router states
*
* A Typescript decorator for declaring a [NgModule](https://angular.io/docs/ts/latest/guide/ngmodule.html)
* which contains UI-Router states.
* A Typescript decorator for declaring an [NgModule](https://angular.io/docs/ts/latest/guide/ngmodule.html)
* which contains UI-Router states and/or uses UI-Router directives and providers.
*
* The decorator adds the `UIRouterLibraryModule` NgModule as an import.
* The `UIRouterLibraryModule has the UI-Router directives and providers.
*
* This decorator analyzes the `states` in the module.
* It adds all routed `component:`(s) for each state to the module's `declarations` and `entryComponents`.
* The decorator also analyzes the `states:` property.
* When it finds a state with a routed `component:`, it adds the component
* to the module's `declarations` and `entryComponents`.
*
* Note: adding the component to `entryComponents` instructs the Module Compiler that those
* components should be compiled.
* Otherwise, they would not be automatically discovered as "reachable" by the compiler.
*
* Further, the states found in the `states:` property are added to Dependency Injection
* using a specific token.
* This will automatically register them with the [[StateRegistry]] when the application bootstraps.
*
* @example
* ```js
Expand All @@ -41,21 +53,23 @@ export const UIROUTER_STATES_TOKEN = new OpaqueToken("UIRouter States");
* var aboutState = { name: 'about', url: '/about', component: About };
*
* @UIRouterModule({
* imports: [BrowserModule],
* declarations: [NonRoutedComponent],
* states: [homeState, aboutState]
* imports: [ BrowserModule ],
* declarations: [ NonRoutedComponent ],
* states: [ homeState, aboutState ]
* }) export class AppModule {};
* ```
*
* The `UIRouterModule` decorator creates an Angular 2 `NgModule`.
* The equivalent `AppModule` could also be crafted by hand using the `NgModule` decorator:
* ---
*
* Note: the `UIRouterModule` decorator creates a standard Angular 2 `NgModule`.
* The equivalent `AppModule` could also be crafted by hand using only the `NgModule` decorator:
*
* ```
* var homeState = { name: 'home', url: '/home', component: Home };
* var aboutState = { name: 'about', url: '/about', component: About };
*
* @NgModule({
* imports: [BrowserModule, UIRouterRootModule],
* imports: [BrowserModule, UIRouterLibraryModule],
* declarations: [NonRoutedComponent, Home, About],
* entryComponents: [Home, About],
* providers: [
Expand All @@ -79,7 +93,7 @@ export function UIRouterModule(moduleMetaData: UIRouterModuleMetadata) {
.reduce((acc, arr) => acc.concat(arr), [])
.filter(x => typeof x === 'function' && x !== UIView);

moduleMetaData.imports = <any[]> (moduleMetaData.imports || []).concat(UIRouterRootModule).reduce(uniqR, []);
moduleMetaData.imports = <any[]> (moduleMetaData.imports || []).concat(UIRouterLibraryModule).reduce(uniqR, []);
moduleMetaData.declarations = <any[]> (moduleMetaData.declarations || []).concat(routedComponents).reduce(uniqR, []);
moduleMetaData.entryComponents = <any[]> (moduleMetaData.entryComponents || []).concat(routedComponents).reduce(uniqR, []);
moduleMetaData.providers = (moduleMetaData.providers || []).concat(statesProvider);
Expand Down

0 comments on commit bc17066

Please sign in to comment.