Angular 1 and Angular 2 Hybrid Application Routing Issue (angular component not displaying)
Asked Answered
R

2

7

I have an Angular 1 and Angular 2 hybrid application that was set-up using the following guides, Upgrading from AngularJS and Migrating Angular 1 Application to Angular 2. My root component looks like this:

import { NgModule, Component } from '@angular/core';
import { RouterModule, UrlHandlingStrategy } from '@angular/router';
import { BrowserModule } from '@angular/platform-browser';
import { UpgradeModule } from '@angular/upgrade/static';
import { RouterUpgradeInitializer } from '@angular/router/upgrade';
import { MyModule } from './Mymodule/my-module';

export class Ng1Ng2UrlHandlingStrategy implements UrlHandlingStrategy {
    shouldProcessUrl(url: any) {
        return url.toString().startsWith("/Mymodule");
    }

    extract(url: any) {
        return url;
    }

    merge(url: any, whole: any) {
        return url;
    }
}

@Component({
    selector: 'root-component',
    template: `
    <router-outlet></router-outlet>
    <div class="ng-view"></div>
  `
})
export class RootComponent { }

@NgModule({
    imports: [
        BrowserModule,
        UpgradeModule,
        MyModule,

        RouterModule.forRoot([])
    ],
    providers: [
        { provide: UrlHandlingStrategy, useClass: Ng1Ng2UrlHandlingStrategy }
    ],
    bootstrap: [RootComponent],
    declarations: [RootComponent]
})
export class Ng2AppModule {
    constructor(public upgrade: UpgradeModule) { }
}

And my "main.ts" is the following:

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { setUpLocationSync } from '@angular/router/upgrade';
import { Ng2AppModule } from "./Angular2/app.rootcomponent";

// This is the entry point for the AngularJS/Angular hybrid application.
// It bootstraps the Angular module 'Ng2AppModule', which in turn bootstraps
// the AngularJS module 'angular1App'.
platformBrowserDynamic().bootstrapModule(Ng2AppModule).then(ref => {
    const upgrade = (<any>ref.instance).upgrade;
    // bootstrap angular1
    upgrade.bootstrap(document.body, ['angular1App']);
    setUpLocationSync(upgrade);
});

The module 'MyModule' follows:

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { TestDataListComponent } from './testdata-list.component';

@NgModule({
    imports: [
        RouterModule.forChild([
            {
                path: 'Mymodule', children: [
                    { path: 'testdata', component: TestDataListComponent }
                ]
            }
        ])
    ],
    declarations: [TestDataListComponent ]
})
export class MyModule {

}

And 'TestDataListComponent' component is very simple:

import { Component } from '@angular/core';

@Component({
    selector: 'test-data',
    templateUrl: 'App/Angular2/MyModule/testdata-list.component'.html'
})
export class TestDataListComponent{

}

The way I am linking to the Angular 2 component is in a main menu HTML page. The relevant code is the following:

<li id="main-menu" class="menu-top-level" ng-mouseover="cur = 'mymodule'">        
    <a ng-reflect-router-link="/Mymodule/testdata" href="#/Mymodule/testdata">
        MyModule
        <span>
            <i class="fa fa-check-square fa-2x"></i>
        </span>
    </a>
</li>

The problem I am experiencing is that clicking on the link above takes me to a blank view, i.e. the component TestDataListComponent is not displayed. However if I replace the following line in my main Angular 2 module, i.e. Ng2AppModule:

RouterModule.forRoot([])

with:

RouterModule.forRoot([], { useHash: true, initialNavigation: false })

component TestDataListComponent shows up fine, but then when I attempt to navigate back to an Angular 1 component, by clicking on a link, the page is blank and what I noticed is that the URL in my browser window looks like this:

http://localhost:60813/#/

while it should looks like this:

http://localhost:60813/#/myclients

If I click on the link a second time, the URL is correct and the Angular 1 component is displayed fine.

The relevant portion of my Angular 1 module angular1App is:

angular.module("angular1App",
["ngRoute",
 "myInterceptorService",
 "ngStorage",
 "ngAnimate",
 "ui.bootstrap",
 "ngResource",
 "SignalR",
 "ui.select",
 "ngSanitize"])
.config([
    "$routeProvider", "$httpProvider", function($routeProvider, $httpProvider) {

        $httpProvider.interceptors.push("myInterceptorService");

        $routeProvider
            .when('/myclients',
            {
                title: "Client Data",
                controller: "clientDataCtrl",
                templateUrl: "/App/Common/Views/clientData.html"
            })

What is the problem here? Why is either my Angular 2 or Angular 1 component now showing up?

Repellent answered 10/7, 2017 at 20:37 Comment(4)
Here is a Plunker that demonstrates the problem: plnkr.co/edit/JGzY1EhulDlrz7gjHxwY?p=previewRepellent
Having similar problems... following the same guide....Enchanter
Any updates? since your last activity here?Enchanter
Yes, look at the following link for the solution to this problem. The Plunker provided by brandonroberts works for me: github.com/angular/angular/issues/18832Repellent
R
1

The solution was provided by brandonroberts on the Angular github. For details, see this issue https://github.com/angular/angular/issues/18832

Excerpt from solution: "The way setupLocationSync provides the URL to the router for navigating doesn't work correctly with hash-based routing. What I did was tweak the source from the setupLocationSync to pass the URL from the hash to navigate with. This way the Router will handle navigating both scenarios correctly."

See the Plunker in the issue above for details.

Repellent answered 7/6, 2018 at 19:1 Comment(0)
J
1

Your problem with component appears to be here:

import { Component } from '@angular/core';

@Component({
    selector: 'test-data',
    templateUrl: 'App/Angular2/MyModule/testdata-list.component'.html'
})
export class TestDataListComponent{

}

You need to add correct templateUrl strin

Judon answered 7/6, 2018 at 16:19 Comment(1)
Please see my answer as well my comment above. This was resolved a while back though I had forgotten to post an official answer here.Repellent
R
1

The solution was provided by brandonroberts on the Angular github. For details, see this issue https://github.com/angular/angular/issues/18832

Excerpt from solution: "The way setupLocationSync provides the URL to the router for navigating doesn't work correctly with hash-based routing. What I did was tweak the source from the setupLocationSync to pass the URL from the hash to navigate with. This way the Router will handle navigating both scenarios correctly."

See the Plunker in the issue above for details.

Repellent answered 7/6, 2018 at 19:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.