Angular and AngularJS Hybrid Application Routing: Angular component as child state not rendering

Issue

first some short introduction to the project and general setup.

It is an Angular/Angular JS application. I integrated Angular couple of weeks ago. In contrast to many different tutorials using the UpgradeModule, I actually had to use the downgradeModule – The project is quite large and UpgradeModule caused a lot of performance issues.

There is an overall Parent State (called app) and I want a Angular Component to be a child of it. According to the docs this should be possible (https://github.com/ui-router/angular-hybrid#limitations)

Limitations:
We currently support routing either Angular (2+) or AngularJS (1.x) components into an AngularJS (1.x) ui-view. However, we do not support routing AngularJS (1.x) components into an Angular (2+) ui-view.

If you create an Angular (2+) ui-view, then any nested ui-view must also be Angular (2+).

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

The general setup looks like this (simplification):

app.module.ng1.ts

import { AppModule } from './app.module';

const bootstrapFn: any = (extraProviders: Array<StaticProvider>): any => {
    return platformBrowserDynamic(extraProviders).bootstrapModule(AppModule);
};
const downgradedModule: any = downgradeModule(bootstrapFn);

const appModule: angular.IModule = angular
    .module('app', [
        downgradedModule,
        // other project modules
    ]);

app.module.ts

@NgModule({
    imports: [
        BrowserModule,
        UIRouterUpgradeModule.forChild(),
    ],
    declarations: [
        AccountNg2Component,
    ],
    providers: [
    ],
    entryComponents: [
        AccountNg2Component,
    ],
})
class AppModule {
    public ngDoBootstrap(): void {}
}

export { AppModule };

TheAccountNg2Component is the one I actually want to go to. account.component.ts

@Component({
    selector: 'account',
    template,
})
class AccountNg2Component {
    @Input() public user: any;

    constructor() {}

}

export { AccountNg2Component };

There is a parent app state and I want the AccountNg2Component to be a child of it. The state configuration looks like this:

$stateProvider
    .state({
        parent: 'app',
        name: 'account',
        url: '/account',
        component: AccountNg2Component,
    });

Whatever I try it will also result in the following two Errors:

Transition Rejection($id: 0 type: 6, message: The transition errored, detail: TypeError: Cannot read property 'when' of undefined)

TypeError: Cannot read property 'when' of undefined
at Ng2ViewConfig.load (views.js:47)
at eval (views.js:19)
at Array.map (<anonymous>)
at loadEnteringViews (views.js:19)
at invokeCallback (transitionHook.js:104)
at TransitionHook.invokeHook (transitionHook.js:116)
at eval (transitionHook.js:58)
at processQueue (angular.js:17169)
at eval (angular.js:17217)
at Scope.$digest (angular.js:18352)
at Scope.$apply (angular.js:18649)
at eval (angular.js:18952)
at completeOutstandingRequest (angular.js:6428)
at eval (angular.js:6707)
at ZoneDelegate.invokeTask (zone.js:420)
at Object.onInvokeTask (core.js:4961)
at ZoneDelegate.invokeTask (zone.js:419)
at Zone.runTask (zone.js:187)
at ZoneTask.invokeTask (zone.js:495)
at ZoneTask.invoke (zone.js:484)
at timer (zone.js:2053)

I’m probably missing something in the configuration, but I’m not able to figure it out.


What I already tried:

I looked at the sample App (https://github.com/ui-router/sample-app-angular-hybrid) and tried to build it as similar as possible. But they are using the UpgradeModule instead of the downgrade – I don’t know if this changes anything for the router.

I tried

The error stays always the same, because of that I think I’m just missing some piece in my configuration.

If my description does not help enough, I’ll try to setup a jsfiddle or something similar


Update 1:
Ok, I removed the state declaration for the account state from the Angular 1 State Provider and instead only register it in the UIRouterModule. Now at least the error is gone, but the state is not loaded at all (when trying to access it, redirect to default state)

Solution

Ok I finally managed to solve the issue, thanks to a tip from a different article (https://stackoverflow.com/a/49568050/4243635)

Just gonna quote it here again:

The Angular bootstrap module needed a parameter of type “UIRouter” in the constructor, otherwise it would not bootstrap its states:

export class AppModule {
       constructor(private router: UIRouter) {
       // "router" needed in constructor to bootstrap angular states
}

You also need to import UpgradeModule and UIRouterUpgradeModule. So the entire app.module.ts looks like this:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ServiceBootstrapComponent } from '../../service-bootstrap';
import { AccountNg2Component } from '../../app/pages/account/account.ng2.component';
import { UIRouterUpgradeModule } from '@uirouter/angular-hybrid';
import { AccountState } from '../../app/pages/account/account.states';
import { CommonModule } from '@angular/common';
import { UIRouter, UIRouterModule } from '@uirouter/angular';
import { UpgradeModule } from '@angular/upgrade/static';

@NgModule({
    imports: [
        CommonModule,
        BrowserModule,
        UpgradeModule,
        UIRouterUpgradeModule,
        UIRouterModule.forChild({states: [AccountState]}),
    ],
    declarations: [
        ServiceBootstrapComponent,
        AccountNg2Component,
    ],
    providers: [
    ],
    entryComponents: [
        ServiceBootstrapComponent,
    ],
})
class AppModule {
    constructor(private router: UIRouter) {}
    public ngDoBootstrap(): void {}
}

export { AppModule };

Answered By – Nicolas Gehlert

Answer Checked By – Cary Denson (AngularFixing Admin)

Leave a Reply

Your email address will not be published.