简体   繁体   中英

Bootstrapped Angular 2 + Angular 1 Hybrid App not loading when using downgradeComponent

I have an Angular 1 app that I've followed the instructions from the official Angular tutorial ( https://angular.io/docs/ts/latest/guide/upgrade.html ) for Bootstrapping a hybrid 1+2 app. I have all the code in place and run the app and absolutely nothing happens. It just goes to the root URL and I only get the styling and view of whatever is in index.html . However the main <div ng-view> never gets updated via $routeProvider and app.ts . At least that appears to be what's happening. There are zero errors. Here is what I have so far:

main.ts (loaded via SystemJS)

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { UpgradeModule } from '@angular/upgrade/static';
import { AppModule } from './app.module';

platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
    const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
    upgrade.bootstrap(document.body, ['MyA1App']);
});

One note for the above hybrid bootstrap code - it is working as far as I can tell. If I change the Angular1 app name to blahblah , I get a whole bunch of errors in the browser. This code can find the MyA1App Angular1 module defined in app.ts and is able to bootstrap it.

index.html :

<div class="main-content" ng-view=""></div>

<!-- Configure SystemJS (bootstrap Angular 2 app) -->
<script src="systemjs.config.js"></script>
<script>
    System.import('app').catch(function(err){ console.error(err); });
</script>

<!-- Old Angular 1 bootstrap method -->
<!--<script>
    angular.bootstrap(document.body, ['MyA1App']);
</script>-->   

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { UpgradeModule } from '@angular/upgrade/static'; //To bootstrap a hybrid application, we  need to import UpgradeModule in our AppModule, and override it's bootstrap method:

@NgModule({
    imports: [BrowserModule, UpgradeModule ],
})

export class AppModule {
    ngDoBootstrap() {}
}

import { downgradeComponent } from '@angular/upgrade/static';
angular.module('MyA1App', [])
    .directive(
    'contactList',
    downgradeComponent({ component: ContactListComponent }) as angular.IDirectiveFactory
    );

app.ts (from Angular 1, which defines the module and routing - this should still be in play and used)

module MyApp {
    'use strict';

export var App: ng.IModule = angular.module('MyA1App', ['ngRoute', 'ngResource', 'highcharts-ng', 'ui.bootstrap']);

    //  register work which needs to be performed on module loading
    App.config([
        '$routeProvider', '$httpProvider',
        ($routeProvider: ng.route.IRouteProvider, $httpProvider: ng.IHttpProvider) => {

            $routeProvider
                .when('/landing',
                {
                    controller: MyApp.Controllers.LandingCtrl,
                    templateUrl: '/app/angular1x/partials/landing.html'
                })
                .when('/registration',
                {
                    controller: MyApp.Controllers.RegistrationCtrl,
                    controllerAs: 'vm',
                    templateUrl: '/app/angular1x/partials/registration.html'
                })               
                .otherwise({
                    redirectTo: '/landing'
                });
        }
    ]);   
}

So here's the overview of the issue:

  • Bootstraping to Angular2 main.ts via systemjs called in index.html (appears successful - no errors)
  • I can place breakpoints in Angular1 controllers, Landing, etc. and see the controllers being defined and loaded being hit. But nothing else happens! No errors or anything.
  • The ng-view directive is never updated via routing. Upon inspecting on the main page it just looks like: <div class="main-content" ng-view=""></div>
  • No JS errors anywhere
  • If I go back and use the original A1 bootstrap in index.html it works as opposed to using systemjs to load A2 and bootstrap A1 as a hybrid.

What am I doing incorrectly here so that the original Angular1 app appears to load and bootstrap just fine, but isn't actually doing anything?


UPDATE:

I have tracked down the offending code to be the following in app.module.ts :

import { downgradeComponent } from '@angular/upgrade/static';
angular.module('MyA1App', [])
    .directive(
    'contactList',
    downgradeComponent({ component: ContactListComponent }) as angular.IDirectiveFactory
    );

It was not the routing (that was a red herring). The entire Angular1 app will bootstrap and load if I remove the code above. What am I doing in the code above that could cause everything to halt loading, yet not create any JavaScript errors?

Well I got to the bottom of this issue and it's disappointing the length of time I waisted because of following the UPGRADING FROM 1.X tutorial. In the tutorial, it shows this exact sample code to downgrade an Angular 2 component by registering it as a directive via the Angular 1 module:

angular.module('heroApp', [])
  .directive(
    'heroDetail',
    downgradeComponent({component: HeroDetailComponent}) as angular.IDirectiveFactory
  );

Notice the empty brackets after the module name [] ? That was the issue. It sent me on a wild goose chase because when I had that in which was directly from the tutorial, I started getting errors about my controllers in Angular1 not being defined. Since a lot of this is still fresh, I went on a wild goose chase stripping parts of my A1 app trying to get things to work thinking they weren't compatible with A2 . It wasn't until I read in that same tutorial that, "The existing Angular 1 code works as before and you're ready to run Angular 2 code" This led me to process of elimination that something in the A2 bootstrap code was wrong and ultimately the brackets caused nothing to load.

My OP noted I wasn't receiving any errors. This was because I had stripped a lot of A1 code trying to make things work and got to a point where the app loaded but nothing was displayed and thought it was a routing issue.

The working code for me is as follows:

angular.module('MyA1App')
    .directive('contactList', downgradeComponent({ component: ContactListComponent }) as angular.IDirectiveFactory);

I have two suggestions:

  1. In your index.html, change <div class="main-content" ng-view=""></div> into <div class="main-content" ui-view></div> .

  2. remove <div class="main-content" ng-view=""></div> from index and add <root-cmp></root-cmp>

Update your app.module.ts like this:

@Component({  
  selector: 'root-cmp',  
  template: '<div class="main-content" ui-view></div>'  
})  
export class RootCmp {
}

@NgModule({  
  imports: [  
    BrowserModule,  
    UpgradeModule  
  ],  
  bootstrap: [RootCmp],  
  declarations: [
    RootCmp
  ],  
  providers: [],  
  entryComponents: [
    RootCmp
  ]  
})  
export class Ng2Module {
  ngDoBootstrap() {
  }
}  

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM