Using Angular Components from Angular JS code

Author: | Posted in Angular, AngularJS, Web No comments

In this post we will take a look at how to use an Angular Components from AngularJS code using UpgradeModule of Angular. Our first goal is to make our application run both Angular and AngularJS in a hybrid mode.

1. Bootstrap as a hybrid application

In order to run both frameworks side-by-side and make components interoperable, the Angular projects comes with a module named UpgradeModule. To bootstrap a hybrid application, you must bootstrap each of the Angular and AngularJS parts of the application. UpgradeModule runs Angular and AngularJS in the same Angular zone. This causes a tight coupling between change detection in Angular and AngularJS.

Step 1: Have all your AngularJS code in a separate folder in your src as shown in the screenshot below. For ex, I have put all my AngularJS code in the folder named app-angularjs

 

Step 2: Install all the dependencies

First and foremost, we need to install Angular, ngUpgrade and all of the peer dependencies.

Inorder to do that, you can just go to your package.json and edit as follows,

 
[package.json]

"dependencies": {
    "@angular/animations": "~7.2.0",
    "@angular/common": "~7.2.0",
    "@angular/compiler": "~7.2.0",
    "@angular/core": "~7.2.0",
    "@angular/forms": "~7.2.0",
    "@angular/platform-browser": "~7.2.0",
    "@angular/platform-browser-dynamic": "~7.2.0",
    "@angular/router": "~7.2.0",
    "@angular/upgrade": "^7.2.3",
    "angular": "1.6.6",
    "angular-route": "1.6.6",
    "bootstrap": "3.3.7",
    "core-js": "^2.5.4",
    "jquery": "^2.2.4",
    "lodash": "4.17.4",
    "moment": "~2.17.1",
    "reflect-metadata": "^0.1.12",
    "rxjs": "~6.3.3",
    "tslib": "^1.9.0",
    "zone.js": "~0.8.26"
  },

Once the packages are added to the file, open your terminal and run npm install, you should see that all of your packages were installed. Or you shall add these angular packages through angular cli.

Step 3: Create an Angular JS module

In an AngularJS application we have a root AngularJS module.

This file named app.module.ts would be under the app-angularjs folder as shown below,

Usually, this module is bootstrapped using the ng-app attribute, but now we want to bootstrap our module using ngUpgrade. So your AngularJS module would be similar to the below code.


 [app-angularjs/app.module.ts]

 import * as angular from 'angular';
 import "angular-route";
 export const angularJSModule = angular.module('angularJSModule', ['ngRoute']);

Now what we’re going to do is export this module and import it into our new Angular module to get it up and running.

Step 4: Bootstrap in the Angular module

The first thing we need to do is to upgrade our Angular 1 application with ngUpgrade. Whenever we upgrade an Angular app, we always have an Angular 1.x module being bootstrap at root level.
Import UpgradeModule in the main Angular application module AppModule.


[app/app.module.ts]

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    UpgradeModule,
    RouterModule.forRoot(routes)
  ],
  bootstrap: [AppComponent]
})

export class AppModule {
  constructor(
    public upgrade: UpgradeModule
  ) { }
}

Next we need to remove the ng-app directive from index.html and implement the ngDoBootstrap method as shown below,


[main.ts]

platformBrowserDynamic().bootstrapModule(AppModule).then(ref => {
  // bootstrap angularJS 
  (ref.instance).upgrade.bootstrap(document.body, [angularJSModule.name]);
})
.catch(err => console.log(err));

2. Downgrade the Angular components as AngularJS directives

Say you have a simple Angular component like the one shown below,


[angular-component.component.ts]

@Component({
  selector: 'app-angular-component',
  templateUrl: './angular-component.component.html',
  styleUrls: ['./angular-component.component.css']
})

export class AngularComponent implements OnInit {

  constructor() { }
  ngOnInit() {
  }
}

If you want to use this component from AngularJS, you need to downgrade it using the downgradeComponent() method. The result would be an AngularJS directive.


[angular-component.component.ts]

import { angularJSModule } from 'src/app-angularjs/app.module';

/* . . . */

import { downgradeComponent } from '@angular/upgrade/static';
@Component({
  selector: 'app-angular-component',
  templateUrl: './angular-component.component.html',
  styleUrls: ['./angular-component.component.css']
})

export class AngularComponent implements OnInit {

/* . . . */

}

// downgrading the component as an angular js directive
angularJSModule
  .directive(
    'angularComponent',
    downgradeComponent({
      component: AngularComponent
    })
  );

The net result is an AngularJS directive called angularComponent, that you can use like any other directive in AngularJS templates.

<angular-component></angular-component>

Because this component is being used from the AngularJS module, and is an entry point into the Angular application, you must add it to the entryComponents for the NgModule.


[app/app.module.ts]

@NgModule({
  declarations: [
    AppComponent,
    AngularComponent
  ],
  imports: [
    BrowserModule,
    UpgradeModule
  ],
  bootstrap: [AppComponent],
  entryComponents: [AngularComponent]
})

export class AppModule {
  constructor(
    public upgrade: UpgradeModule
  ) { }
}

The above downgraded Angular component can be used in an Angular JS template


[app-angularjs/sample.html]

<div>
    <angular-component></angular-component>
</div>

Sample code can be found at https://github.com/sonakrishnan/ng-hybrid-app

Add Your Comment