Skip to content

Commit f4bb925

Browse files
fix(upgrade): Fix "Trying to get the AngularJS injector before it being set" in child and lazy modules
Split `UIRouterUpgradeModule.forChild()` into `.forRoot()` and `.forChild()` BREAKING CHANGE: In 5.0.0, we recommended `UIRouterUpgradeModule.forChild()` everywhere. However, this could cause an error "Trying to get the AngularJS injector before it being set". Now: - Use `UIRouterUpgradeModule.forRoot()` in the root Angular module. - Use `UIRouterUpgradeModule.forChild()` for Angular feature modules and lazy loaded modules. Closes #93
1 parent c0e55ad commit f4bb925

File tree

3 files changed

+54
-52
lines changed

3 files changed

+54
-52
lines changed

README.md

Lines changed: 45 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,14 @@ Add the `@angular/*` dependencies.
5151
```
5252
dependencies: {
5353
...
54-
"@angular/common": "^4.0.0",
55-
"@angular/compiler": "^4.0.0",
56-
"@angular/core": "^4.0.0",
57-
"@angular/platform-browser": "^4.0.0",
58-
"@angular/platform-browser-dynamic": "^4.0.0",
59-
"@angular/upgrade": "^4.0.0",
54+
"@angular/common": "^6.0.0",
55+
"@angular/compiler": "^6.0.0",
56+
"@angular/core": "^6.0.0",
57+
"@angular/platform-browser": "^6.0.0",
58+
"@angular/platform-browser-dynamic": "^6.0.0",
59+
"@angular/upgrade": "^6.0.0",
6060
...
61-
"@uirouter/angular-hybrid": "^3.0.1",
61+
"@uirouter/angular-hybrid": "^6.0.0",
6262
...
6363
}
6464
```
@@ -78,7 +78,7 @@ let ng1module = angular.module('myApp', ['ui.router', 'ui.router.upgrade']);
7878

7979
#### Create a root Angular NgModule
8080

81-
* Import the `BrowserModule`, `UpgradeModule`, and a `UIRouterUpgradeModule.forChild()` module.
81+
* Import the `BrowserModule`, `UpgradeModule`, and a `UIRouterUpgradeModule.forRoot()` module.
8282
* Add `providers` entry for any AngularJS services you want to expose to Angular.
8383
* The module should have a `ngDoBootstrap` method which calls the `UpgradeModule`'s `bootstrap` method.
8484

@@ -90,24 +90,31 @@ export function getDialogService($injector) {
9090
@NgModule({
9191
imports: [
9292
BrowserModule,
93+
// Provide angular upgrade capabilities
9394
UpgradeModule,
94-
UIRouterUpgradeModule.forChild({ states: ngHybridStates }),
95+
// Provides the @uirouter/angular directives and registers
96+
// the future state for the lazy loaded contacts module
97+
UIRouterUpgradeModule.forRoot({ states: [contactsFutureState] }),
9598
],
9699
providers: [
100+
// Provide the SystemJsNgModuleLoader when using Angular lazy loading
97101
{ provide: NgModuleFactoryLoader, useClass: SystemJsNgModuleLoader },
102+
98103
// Register some AngularJS services as Angular providers
99104
{ provide: 'DialogService', deps: ['$injector'], useFactory: getDialogService },
105+
{ provide: 'Contacts', deps: ['$injector'], useFactory: getContactsService },
100106
]
101-
}) export class SampleAppModule {
107+
})
108+
export class SampleAppModuleAngular {
102109
constructor(private upgrade: UpgradeModule) { }
103110

104111
ngDoBootstrap() {
105-
this.upgrade.bootstrap(document.body, [sampleAppModuleAngularJS.name]);
112+
this.upgrade.bootstrap(document.body, [sampleAppModuleAngularJS.name], { strictDi: true });
106113
}
107114
}
108115
```
109116

110-
[_example_](https://github.com/ui-router/sample-app-angular-hybrid/blob/e4b1144d5e3e3451f0f0cc640175bb7055294fdd/app/bootstrap/bootstrap.ts#L63-L73)
117+
[_example_](https://github.com/ui-router/sample-app-angular-hybrid/blob/878095bc7ed1948bb8ebf6e67d77724354393455/app/angularModule.ts#L26-L53)
111118

112119
#### Defer intercept
113120

@@ -117,7 +124,7 @@ Tell UI-Router that it should wait until all bootstrapping is complete before do
117124
ngmodule.config(['$urlServiceProvider', ($urlService: UrlService) => $urlService.deferIntercept()]);
118125
```
119126

120-
[_example_](https://github.com/ui-router/sample-app-angular-hybrid/blob/e4b1144d5e3e3451f0f0cc640175bb7055294fdd/app/bootstrap/bootstrap.ts#L75-L76)
127+
[_example_](https://github.com/ui-router/sample-app-angular-hybrid/blob/878095bc7ed1948bb8ebf6e67d77724354393455/app/main.ts#L38-L40)
121128

122129
#### Bootstrap the app
123130

@@ -127,28 +134,24 @@ ngmodule.config(['$urlServiceProvider', ($urlService: UrlService) => $urlService
127134
* Do this in the Angular Zone to avoid "digest already in progress" errors.
128135

129136
```js
130-
// Wait until the DOM is ready
131-
angular.element(document).ready(function() {
132-
// Manually bootstrap the Angular app
133-
platformBrowserDynamic()
134-
.bootstrapModule(SampleAppModule)
135-
.then(platformRef => {
136-
// get() UrlService from DI (this call will create all the UIRouter services)
137-
const url: UrlService = platformRef.injector.get(UrlService);
138-
139-
// Instruct UIRouter to listen to URL changes
140-
function startUIRouter() {
141-
url.listen();
142-
url.sync();
143-
}
144-
145-
const ngZone: NgZone = platformRef.injector.get(NgZone);
146-
ngZone.run(startUIRouter);
147-
});
148-
});
137+
platformBrowserDynamic()
138+
.bootstrapModule(SampleAppModuleAngular)
139+
.then(platformRef => {
140+
// Intialize the Angular Module
141+
// get() the UIRouter instance from DI to initialize the router
142+
const urlService: UrlService = platformRef.injector.get(UIRouter).urlService;
143+
144+
// Instruct UIRouter to listen to URL changes
145+
function startUIRouter() {
146+
urlService.listen();
147+
urlService.sync();
148+
}
149+
150+
platformRef.injector.get < NgZone > NgZone.run(startUIRouter);
151+
});
149152
```
150153

151-
[_example_](https://github.com/ui-router/sample-app-angular-hybrid/blob/e4b1144d5e3e3451f0f0cc640175bb7055294fdd/app/bootstrap/bootstrap.ts#L78-L95)
154+
[_example_](https://github.com/ui-router/sample-app-angular-hybrid/blob/878095bc7ed1948bb8ebf6e67d77724354393455/app/main.ts#L42-L55)
152155

153156
#### Route to AngularJS components/templates
154157

@@ -199,29 +202,18 @@ $stateProvider.state(leaf);
199202
export class MyFeatureModule {}
200203
```
201204

202-
[_example_](https://github.com/ui-router/sample-app-angular-hybrid/blob/e4b1144d5e3e3451f0f0cc640175bb7055294fdd/app/prefs/index.ts#L11-L22)
205+
[_example_](https://github.com/ui-router/sample-app-angular-hybrid/blob/878095bc7ed1948bb8ebf6e67d77724354393455/app/prefs/prefs.module.ts#L10-L21
203206

204207
Add the feature module to the root NgModule imports
205208

206209
```js
207210
@NgModule({
208-
imports: [BrowserModule, UIRouterUpgradeModule, MyFeatureModule],
211+
imports: [BrowserModule, UIRouterUpgradeModule.forChild({ states }), MyFeatureModule],
209212
})
210213
class SampleAppModule {}
211214
```
212215

213-
[_example_](https://github.com/ui-router/sample-app-angular-hybrid/blob/e4b1144d5e3e3451f0f0cc640175bb7055294fdd/app/bootstrap/bootstrap.ts#L64)
214-
215-
Note: You can also add states directly to the root NgModule using `UIRouterModule.forChild`
216-
217-
```js
218-
@NgModule({
219-
// import the Ng1ToNg2Module and create a UIRouter "child module"
220-
imports: [BrowserModule, UIRouterUpgradeModule.forChild({ states: NG2_STATES })],
221-
declarations: [NG2_COMPONENTS],
222-
})
223-
class SampleAppModule {}
224-
```
216+
[_example_](https://github.com/ui-router/sample-app-angular-hybrid/blob/878095bc7ed1948bb8ebf6e67d77724354393455/app/angularModule.ts#L35-L36)
225217

226218
### Limitations:
227219

@@ -235,7 +227,7 @@ Because of this, apps should be migrated starting from leaf states/views and wor
235227
---
236228

237229
When a state has an `onEnter`, `onExit`, or `onRetain`, they are always injected (AngularJS style),
238-
even if the state uses Angular 2+ components or is added to an `UIRouterUpgradeModule.forChild` `NgModule`.
230+
even if the state uses Angular 2+ components or is added to an `UIRouterUpgradeModule` `NgModule`.
239231

240232
```js
241233
export function ng2StateOnEnter(transition: Transition, svc: MyService) {
@@ -254,7 +246,10 @@ export const NG2_STATE = {
254246
The minimal example of `@uirouter/angular-hybrid` can be found here:
255247
https://github.com/ui-router/angular-hybrid/tree/master/example
256248

257-
A full fledged sample application example can be found here:
249+
A minimal example can also be found on stackblitz:
250+
https://stackblitz.com/edit/ui-router-angular-hybrid
251+
252+
A large sample application example with lazy loaded modules can be found here:
258253
https://github.com/ui-router/sample-app-angular-hybrid
259254

260255
The same sample application can be live-edited using Angular CLI and StackBlitz here:
@@ -263,5 +258,5 @@ https://stackblitz.com/github/ui-router/sample-app-angular-hybrid/tree/angular-c
263258
# UpgradeAdapter vs UpgradeModule
264259

265260
Version 2.0.0 of `@uirouter/angular-hybrid` only supports `UpgradeAdapter`, which works fine but is no longer in development.
266-
Version 30.0+ of `@uirouter/angular-hybrid` only supports `UpgradeModule` from `@angular/upgrade/static`, which is what the Angular team actively supports for hybrid mode.
261+
Version 3.0.0+ of `@uirouter/angular-hybrid` only supports `UpgradeModule` from `@angular/upgrade/static`, which is what the Angular team actively supports for hybrid mode.
267262
Because we dropped support for `UpgradeAdapter`, current users of `@uirouter/angular-hybrid` 2.x will have to switch to `UpgradeModule` when upgrading to 3.x.

example/src/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ const nestedState: NgHybridStateDeclaration = {
8787
// Provide Angular upgrade capabilities
8888
UpgradeModule,
8989
// Provides the @uirouter/angular directives
90-
UIRouterUpgradeModule.forChild({ states: [nestedState] }),
90+
UIRouterUpgradeModule.forRoot({ states: [nestedState] }),
9191
],
9292
declarations: [Ng2Component],
9393
entryComponents: [Ng2Component],

src/angular-hybrid.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,12 +201,19 @@ export function getParentUIViewInject(r: StateRegistry): ParentUIViewInject {
201201
exports: [UIViewNgUpgrade, UIRouterModule],
202202
})
203203
export class UIRouterUpgradeModule {
204-
static forChild(module: NgHybridStatesModule = {}): ModuleWithProviders {
204+
static forRoot(module: NgHybridStatesModule = {}): ModuleWithProviders {
205205
return {
206206
ngModule: UIRouterUpgradeModule,
207207
providers: makeChildProviders(module as StatesModule),
208208
};
209209
}
210+
211+
static forChild(module: NgHybridStatesModule = {}): ModuleWithProviders {
212+
return {
213+
ngModule: UIRouterModule,
214+
providers: makeChildProviders(module as StatesModule),
215+
};
216+
}
210217
}
211218

212219
// Downgrade the UIViewNgUpgrade ng2 Component to an ng1 directive.

0 commit comments

Comments
 (0)