Angular(JS)

Angular(JS) like it’s 2019

Angular(JS)

How to upgrade Angular (JS) to Angular 7?

You must have been asleep (for a few years at least) because Angular 7.x is already here and you’re still stuck on AngularJS. Or maybe it’s just that your codebase is so damn large you can’t face wasting years of your life rewriting it all at once? 

Fear not! It’s not that bad. You can (and should!) upgrade to Angular 7 step by step, or you can do it while leaving your old code in place, working with the latest Angular shipping new features.

But how? Simple. By choosing the Hybrid Application path. This means we will be able to expand our old app with the new Angular, running both frameworks at the same time.

In my opinion, the best way to understand any tool is to in fact dig into the code itself.  So I have prepared a small (really the bare minimum!) repository to use as an Angular upgrade example to show off the process of upgrading.

Prerequisites

Well, actually there aren’t that many prerequisites that your project must follow to be able to upgrade.  All the in-depth details are, as always, in Angular Docs.

Also, these are the things you can do if you like but you are not really obliged to do; some are just for helping you get through the upgrading process (like sticking to the style guide).

To name a few:

  1. Following the AngularJS Style Guide 
  2. Using a Module Bundler: but who doesn’t these days?
  3. TypeScript: this is a must, but you probably already know that
  4. Component Directives: just a good step forward you should already be using if you’re on AngularJS >= 1.5

UpgradeModule to the rescue

Have I mentioned the hybrid app already? Because this seems like a good moment to put in a few more words on it.

The Angular Hybrid app is just like any other, but it comes packed with two versions of Angular; the good ol AngularJS and one of the latest/newest Angular versions (you’re probably reading this with somewhere around Angular 7 / 8 out there, or maybe even 9? 10…?).

Angular comes with a handy UpgradeModule which will help us bootstrap the hybrid application.

The next part of this post will cover the tools inside this module to help you bootstrap, and upgrade/downgrade the components.

Bootstrapping

While we usually/sometimes bootstrap AngularJS app automagically from HTML, like this:

<!doctype html>
<html ng-app="app">
<head>
  <meta charset="UTF-8">
  <title>ng Hybrid App</title>
</head>
<body>
  <app></app>
</body>
</html>

working with the hybrid application requires bootstrapping manually two modules, one for each ng version (more on this below). So, it’s necessary to replace the auto bootstrap with manual in your ng1.x app:

import * as angular from 'angular';

import { AppComponent } from './components/app/app.component';
import { WhatAmIComponent } from './components/whatAmI/whatAmI.component';

angular
  .module("app",[])
  .component(AppComponent.selector, new AppComponent())
  .component(WhatAmIComponent.selector, new WhatAmIComponent());

angular
  .bootstrap(document, ['app']);

Who doesn’t like more npm dependencies?

First of all, let’s introduce some Angular dependencies into our project, namely:

  • @angular/core: 
  • @angular/common: 
  • @angular/compiler: 
  • @angular/platform-browser: 
  • @angular/platform-browser-dynamic: 
  • @angular/upgrade: 
  • rxjs

These aren’t all Angular comes with, but they’re enough to do an upgrade. You’ll probably install some more while working with the code e.g. @angular/router, @angular/forms and so on.

Besides Angular itself, we’ll need some polyfills:

  • core-js
  • zone.js

You’ll find the current state of the package.json here: https://github.com/kamil-maslowski/ng-hybrid-app/blob/upgrade-packages/package.json.

{
  "name": "hybrid-app",
  "version": "0.0.1",
  "description": "",
  "scripts": {
    "build": "webpack --config webpack.config.js"
  },
  "author": "Kamil Maslowski",
  "license": "ISC",
  "dependencies": {
    "@angular/common": "^7.2.12",
    "@angular/compiler": "^7.2.12",
    "@angular/core": "^7.2.12",
    "@angular/platform-browser": "^7.2.12",
    "@angular/platform-browser-dynamic": "^7.2.12",
    "@angular/upgrade": "^7.2.12",
    "angular": "^1.7.8",
    "core-js": "^3.0.0",
    "rxjs": "^6.4.0",
    "zone.js": "^0.8.29"
  },
  "devDependencies": {
    "@types/angular": "^1.6.54",
    "html-webpack-plugin": "^3.2.0",
    "ts-loader": "^5.3.3",
    "typescript": "^3.4.1",
    "webpack": "^4.29.6",
    "webpack-cli": "^3.3.0"
  }
}

The order of things to upgrade Angular

AJS module

Now we need to make some changes in the project structure. Our old place-where-it-all-started was here, let’s rename it as ajs.module.ts. 

We also need to remove the line:

angular
  .bootstrap(document, ['app']);

Why do we do this? As I’ve already mentioned, we need two modules, AJS will act as our AngularJS module, and the bootstrapping will be handled by the Angular UpgradeModule tools.

App module

Our app.module:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { UpgradeModule } from '@angular/upgrade/static';

@NgModule({
  imports: [
    BrowserModule,
  ]
})
export class AppModule {
  constructor(private upgrade: UpgradeModule) { }
  ngDoBootstrap() {
    this.upgrade.bootstrap(document.documentElement, ['app']);
  }
}

namely the place where we will bootstrap the Angular app (now along with AngularJS) is really simple. We just need to import the bare minimum and export a module, overriding the ngDoBootstrap.

Index.ts reinvented

So the main entry point of our app, index.ts, now looks like this

import 'core-js/proposals/reflect-metadata';
import 'zone.js';

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

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

platformBrowserDynamic().bootstrapModule(AppModule);

First, we’ll import some polyfills Angular will need to support all the latest mojos not yet in some of the browsers.  For overall info on that check out the Angular Browser Docs

Then platform-browser-dynamic, already covered above, our AngularJS and Angular modules, and well – that’s all we need here.

The last step now is just to bootstrap the app!

platformBrowserDynamic().bootstrapModule(AppModule);

Hybrid app ready to run!

Now we already have a working, hybrid angular application. But no need to take my word for it.  Just run:

{ "build": "webpack --config webpack.config.js" }

and check out yourself the dist folder. So why almost? Because I’d like to also show you how to take your first baby-steps in your fancy new hybrid app. We’re going to write an Angular component, and downgrade it to make it usable inside the AngularJS code. Let’s do it!

First steps in your hybrid app

Let’s create a new component under the src/components. We’ll call it whatIdLikeToBe.component.ts. We’ll create this component in Angular style, exporting the component class annotated with Component from the @angular/core package. As it’s a template (remember we can also use templateUrl instead of the inline template!) we just have to put in a simple string.

You’ll find the source below

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

@Component({
  selector: 'what-id-like-to-be',
  template: `
    <h2>yay! I'm an ng6 component!</h2>
  `
})
export default class WhatIdLikeToBeComponent { }

What next? Next, we want to be able to use our brand new Angular component in our Angular Hybrid App. To be able to do that we have to tell Angular(JS) that we have some component that it needs to downgrade to 1.x format, so…

import * as angular from 'angular';

import { AppComponent } from './components/app/app.component';
import { WhatAmIComponent } from './components/whatAmI/whatAmI.component';
import { downgradeComponent } from '@angular/upgrade/static';
import WhatIdLikeToBeComponent from './components/whatIdLikeToBe/whatIdLikeToBe.component';

angular
  .module("app",[])
  .component(AppComponent.selector, new AppComponent())
  .component(WhatAmIComponent.selector, new WhatAmIComponent())
  .directive(
    'whatIdLikeToBe',
    downgradeComponent({ component: WhatIdLikeToBeComponent })
  );

See what we did there? We downgraded our component to the AngularJS directive specifying a directive name (spot the camelCase here, it’s easy to mix up where to use camelCase vs kebab-case). And that’s all we need! Our Angular component can now be used anywhere in the AngularJS codebase, like this:

export class AppComponent implements ng.IComponentController, ng.IComponentOptions {
  static selector = 'app';
  controller: ng.Injectable<ng.IControllerConstructor> = AppComponent;
  template: string = `
    <h1>Upgrade me!</h1>
    <div>
      <what-am-i></what-am-i>
      <what-id-like-to-be></what-id-like-to-be>
    </div>
  `;
}

Once more, spot how we specified the camelCase directive name vs how we use it with kebab-case here!

Conclusions on Angular upgrade

Reading the intro you were probably thinking:  “Wait a moment! How to upgrade to Angular 7? But we’re already on v. 8/9/2802 ”. And yes, you’d be completely right, which shows how often Angular is updated (in fact there’s a major new version every six months). So there’s no time to lose to start upgrading!

You may, of course, be happy with the current source code that backs your projects, but as time passes, and literally everyday tech stacks develop more and more, it’s worth checking out what’s out there. Not only for the sake of developers, but also for the sake of your end-users, whose user experience will be improved for numerous reasons, not least because of the performance boosts you can achieve and all the mojos made available to you by the Angular team.

Read also

More frontend content

Download e-book:

Scalac Case Study Book

Download now

Authors

Kamil Masłowski
Kamil Masłowski

My journey into professional software engineering started in 2009. Since that time, I have gained experience both with frontend as well as backend solutions. In the last five years, I've spent working with frontend in agile environments, as well as startups. My current framework-of-choice is Angular.

Latest Blogposts

19.07.2024 / By 

CrowdStrike Falcon Down: How a single security update shutdown Windows worldwide

Today, on July 19, 2024, a CrowdStrike code update led to global issues affecting Windows computers. The operating systems crashed repeatedly, displaying Blue Screen of Death (BSoD), keeping them in a non-usable loop state. This outage caused around 1400 flights to be cancelled, as well as numerous services to be stuck in a dysfunctional state: […]

27.06.2024 / By 

Scalendar July 2024

Welcome to the July edition of our newsletter! We bring you the latest updates on Scala conferences in July 2024, as well as frontend development and software architecture events. There are several conferences and meetups this month for developers of all levels, despite the start of a vacation season. Whether you’re looking to deepen your […]

19.06.2024 / By 

How Akka Specialists Drive Innovation in Software Projects

Akka Specialists

Why do you need Akka Specialists? Today’s global software development ecosystem is, to say the least, fast-paced, dynamic, and diverse. Every company, even partially operating in it, should always keep its finger on the pulse – innovation is the key to staying ahead of the competition. Companies constantly look for new ways to improve the […]

software product development

Need a successful project?

Estimate project