Skip to content

Commit

Permalink
feat(bootstrap): Release 1.0.12: Support angular 2.0.1 and ui-router …
Browse files Browse the repository at this point in the history
…1.0.0-beta.3+
  • Loading branch information
christopherthielen committed Sep 23, 2016
1 parent 5cb5e11 commit 2e6c4f7
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 73 deletions.
116 changes: 84 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

### Hybrid Angular 1/Angular 2 UI-Router apps

This module provides [ngUpgrade](https://angular.io/docs/ts/latest/guide/upgrade.html) support for UI-Router, allowing hybrid ng1/ng2 UI-Router apps.
This module provides [ngUpgrade](https://angular.io/docs/ts/latest/guide/upgrade.html) integration
with UI-Router, enabling routing to both Angular 1 and Angular 1 Components (and/or templates).

Your app will be hosted on Angular 1 while you incrementally upgrade it to Angular 2.
With `ng1-to-ng2`, you can use either an Angular 1 or Angular 2 Component as a view in your state definitions.
With `ui-router-ng1-to-ng2`, you can use either an Angular 1 or Angular 2 component as a view in your state definitions.

```js
import { Ng2AboutComponent } from "./about.ng2.component";
Expand All @@ -15,26 +16,28 @@ import { Ng2AboutComponent } from "./about.ng2.component";
$stateProvider.state({
name: 'home',
url: '/home',
component: 'ng1HomeComponent' // ng1 component name
component: 'ng1HomeComponent' // ng1 component or directive name
})

.state({
name: 'about',
url: '/about',
component: Ng2AboutComponentClass // ng2 component class reference
});
```

When routing to an ng2 component, that component uses the
[ng2 directives (ui-view and uiSref) from `ui-router-ng2`](https://ui-router.github.io/docs/latest/modules/ng2_directives.html).
We do not yet support nesting an angular 1 directive inside an angular 2 ui-view.
Because of this, apps should be migrated starting from leaf views and work up towards the root state.
.state({
name: 'other',
url: '/other',
template: '<h1>Other</h1>', // ng1 template/controller
controller: function($scope) { /* do stuff */ }
})

See the [hybrid sample app](https://github.com/ui-router/sample-app-ng1-to-ng2) for full example.
```

When routing to an ng2 component, that ng2 component uses the standard
[ng2 directives (ui-view and uiSref) from `ui-router-ng2`](https://ui-router.github.io/docs/latest/modules/ng2_directives.html).

*NOTE: ui-router-ng1-to-ng2 version 1.0.11 currently supports only Angular 2.0.0-rc.5*
See https://github.com/ui-router/ng1-to-ng2/issues/13
See the [hybrid sample app](https://github.com/ui-router/sample-app-ng1-to-ng2) for a full example.

### Getting started

Expand All @@ -43,38 +46,50 @@ Add `@angular`, `ui-router-ng2`, and `ui-router-ng1-to-ng2` to your package.json
```
dependencies: {
...
"@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/upgrade": "=2.0.0-rc.5",
"@angular/common": "~2.0.1",
"@angular/compiler": "~2.0.1",
"@angular/core": "~2.0.1",
"@angular/platform-browser": "~2.0.1",
"@angular/platform-browser-dynamic": "~2.0.1",
"@angular/upgrade": "~2.0.1",
...
"ui-router-ng2": "^1.0.0-beta.2",
"ui-router-ng1-to-ng2": "^1.0.11",
"ui-router-ng2": "^1.0.0-beta.3",
"ui-router-ng1-to-ng2": "^1.0.12",
}
```

#### Switch your app from bootstrapping using `ng-app` to using the ngUpgrade manual bootstrap
#### Bootstrapping a hybrid app

Switch your app from bootstrapping using `ng-app` to using the `ngUpgrade` manual bootstrap

```js
// Add 'ui.router.upgrade' to your ng1 app module's depedencies
let ng1module = angular.module("myApp", [uiRouter, 'ui.router.upgrade']);
```

```js
// Create an Angular 2 root NgModule
@NgModule({
// import the Ng1ToNg2Module
imports: [ BrowserModule, Ng1ToNg2Module ]
}) class SampleAppModule {}

// Create an upgrade adapter instance
import {UpgradeAdapter} from '@angular/upgrade';
export const upgradeAdapter = new UpgradeAdapter();
let upgradeAdapter = new UpgradeAdapter(SampleAppModule);

// Supply ui-router-ng1-to-ng2 with the upgrade adapter
import {uiRouterNgUpgrade} from "ui-router-ng1-to-ng2";
uiRouterNgUpgrade.setUpgradeAdapter(upgradeAdapter);

// Manually bootstrap the app with the Upgrade Adapter (instead of ng-app)
// Add 'ui.router.upgrade' to your apps module depedencies
upgradeAdapter.bootstrap(document.body, ['myApp', 'ui.router.upgrade']);
upgradeAdapter.bootstrap(document.body, ['myApp']);
```

#### Route to ng2 components

#### Route to components

Use `component:` in your state declaration
Register states using either Angular 1 or Angular 2 code.
Use `component:` in your state declaration.

```
var leaf = {
Expand All @@ -85,12 +100,49 @@ var leaf = {
$stateProvider.state(leaf);
```

#### Declare ui-view at the top level of your application
#### Create ng2 Feature Modules (optional)

```js
@NgModule({
imports: [
UIRouterModule.forChild({
states: [featureState1, featureState2]
})
],
declarations: [FeatureComponent1, FeatureComponent2]
})
export class MyFeatureModule {}
```

Add the feature module to the root NgModule imports
```js
@NgModule({
// import the Ng1ToNg2Module
imports: [ BrowserModule, Ng1ToNg2Module, MyFeatureModule ]
}) class SampleAppModule {}
```
<html>
<body>
<ui-view></ui-view>
</body>
</html>

Note: You can also add states directly to the root NgModule using `UIRouterModule.forChild`
```js
@NgModule({
// import the Ng1ToNg2Module and create a UIRouter "child module"
imports: [
BrowserModule,
Ng1ToNg2Module,
UIRouterModule.forChild({ states: NG2_STATES })
],
declarations: [NG2_COMPONENTS]
}) class SampleAppModule {}
```

### Limitations:

We currently support creating a `<ui-view>` in an Angular 1 view,
then routing to Angular 1 or Angular 2 components inside that angular 1 `ui-view`.

We do not (yet) support creating a nested `ui-view` in Angular 2, then routing to an angular 1 component.
Once an Angular 2 component has been routed to, any `<ui-view>` inside the Angular 2 component can only be
targeted by other Angular 2 components.

Because of this, apps should be migrated starting from leaf states/views and work up towards the root state/view.

34 changes: 21 additions & 13 deletions ng1-to-ng2.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import * as angular from "angular";
import {Ng1ViewConfig, $InjectorLike} from "angular-ui-router";
import {Ng1ViewConfig, $InjectorLike, StateProvider, State} from "angular-ui-router";

import {ElementRef, Component, Input, Inject, NgModule} from "@angular/core";
import {UpgradeAdapter} from "@angular/upgrade";

import {
UIRouter, ViewService, StateRegistry, StateProvider,
UIView, Ng2ViewDeclaration, Ng2ViewConfig, State, PathNode, Resolvable,
ParentUIViewInject, ViewConfig, forEach, UIRouterRx,
NG2_INJECTOR_TOKEN, ngModuleResolvablesBuilder, UIRouterLibraryModule
UIRouter, ViewService, StateRegistry,
UIView, Ng2ViewDeclaration, Ng2ViewConfig, PathNode, Resolvable,
ParentUIViewInject, ViewConfig, forEach, UIRouterRx,
NATIVE_INJECTOR_TOKEN, _UIROUTER_SERVICE_PROVIDERS, UIRouterModule, UIROUTER_ROOT_MODULE
} from "ui-router-ng2";

/**
Expand Down Expand Up @@ -137,8 +137,12 @@ export class UIViewNgUpgrade {
* This NgModule should be added to the root module of the hybrid app.
*/
@NgModule({
imports: [UIRouterLibraryModule],
imports: [UIRouterModule],
declarations: [UIViewNgUpgrade],
providers: [
..._UIROUTER_SERVICE_PROVIDERS,
{ provide: UIROUTER_ROOT_MODULE, useValue: {}, multi: true }
],
exports: [UIViewNgUpgrade]
}) export class Ng1ToNg2Module {}

Expand Down Expand Up @@ -171,11 +175,17 @@ function applyHybridAdapter(upgradeAdapter: UpgradeAdapter) {
let $uiRouter: UIRouter = ng1Injector.get('$uiRouter');
new UIRouterRx($uiRouter);

// Expose the root ng2 Injector as a Resolvable (on the root state).
// This mirrors what ui-router-ng2 does in its initialization code
const getNg2Injector = () =>
ng1Injector.get('ng2.Injector');
let ng2InjectorResolvable = new Resolvable(NG2_INJECTOR_TOKEN, getNg2Injector, [], { when: "EAGER" });
// Expose a merged ng1/ng2 injector as a Resolvable (on the root state).
// This mimics how ui-router-ng2 exposes the root ng2 Injector, but
// it retrieves from ng1 injector first, then ng2 injector if the token isn't found.
const mergedInjector = {
get: function(token: any, ng2NotFoundValue?: any) {
let ng2Injector = ng1Injector.get('ng2.Injector');
return (ng1Injector.has(token) && ng1Injector.get(token)) || ng2Injector.get(token, ng2NotFoundValue)
}
};

let ng2InjectorResolvable = Resolvable.fromData(NATIVE_INJECTOR_TOKEN, mergedInjector);
$uiRouter.stateRegistry.root().resolvables.push(ng2InjectorResolvable);
}]);

Expand Down Expand Up @@ -209,8 +219,6 @@ function applyHybridAdapter(upgradeAdapter: UpgradeAdapter) {
});
return views;
});

$stateProvider.decorator('resolvables', ngModuleResolvablesBuilder);
}]);


Expand Down
30 changes: 14 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ui-router-ng1-to-ng2",
"version": "1.0.11",
"version": "1.0.12",
"scripts": {
"all": "npm run clean && npm run build && npm run bundle",
"clean": "rm -rf ng1-to-ng2.d.ts ng1-to-ng2*.js ng1-to-ng2*.js.map build",
Expand All @@ -12,31 +12,29 @@
"license": "MIT",
"peerDependencies": {
"angular": "^1.5.0",
"@angular/core": "~2.0.0",
"@angular/upgrade": "~2.0.0",
"core-js": "^2.4.1",
"@angular/core": "~2.0.1",
"@angular/upgrade": "~2.0.1",
"rxjs": "~5.0.0-beta.12",
"angular-ui-router": "^1.0.0-beta.2",
"ui-router-ng2": "^1.0.0-beta.2",
"angular-ui-router": "^1.0.0-beta.3",
"ui-router-ng2": "^1.0.0-beta.3",
"zone.js": "~0.6.21"
},
"devDependencies": {
"@angular/common": "~2.0.0",
"@angular/compiler": "~2.0.0",
"@angular/core": "~2.0.0",
"@angular/platform-browser": "~2.0.0",
"@angular/platform-browser-dynamic": "~2.0.0",
"@angular/upgrade": "~2.0.0",
"@angular/common": "~2.0.1",
"@angular/compiler": "~2.0.1",
"@angular/core": "~2.0.1",
"@angular/platform-browser": "~2.0.1",
"@angular/platform-browser-dynamic": "~2.0.1",
"@angular/upgrade": "~2.0.1",
"@types/angular": "^1.5.14",
"@types/core-js": "^0.9.28",
"@types/jquery": "^1.10.31",
"@types/node": "^6.0.31",
"angular": "~1.5.3",
"angular-ui-router": "^1.0.0-beta.2",
"angular-ui-router": "^1.0.0-beta.3",
"awesome-typescript-loader": "^2.2.4",
"rxjs": "~5.0.0-beta.12",
"systemjs": "0.19.25",
"typescript": "^2.0.2",
"ui-router-ng2": "^1.0.0-beta.2",
"ui-router-ng2": "^1.0.0-beta.3",
"webpack": "^1.13.1",
"zone.js": "~0.6.21"
},
Expand Down
15 changes: 3 additions & 12 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"lib": ["es6", "dom"],
"sourceMap": true,
"pretty": true,
"declaration": true,
Expand All @@ -12,17 +13,7 @@
"removeComments": false,
"noImplicitAny": false,
"suppressExcessPropertyErrors": true,
"suppressImplicitAnyIndexErrors": true,
"types": [
"core-js",
"node",
"jquery",
"angular"
]
"suppressImplicitAnyIndexErrors": true
},
"exclude": [
"node_modules"
],
"compileOnSave": false,
"buildOnSave": false
"exclude": [ "node_modules" ]
}

0 comments on commit 2e6c4f7

Please sign in to comment.