Despite the fact that the first stable version of Angular 2 was released in the third quarter of 2016, and Angular has already reached version 6, many of us still maintain and develop applications written in AngularJS (Angular 1.x), but why is the issue of angularjs to angular migration still relevant and how to implement it in practice? In this article, I will show you how to migrate a project from AngularJS to Angular.
Migrating an existing application written in AngularJS to the latest version of Angular can be quite a challenge. Especially if our application has many components, services, and views. Many people associate this process with rewriting the application from scratch. However, not every team can afford a few months of downtime to add new functionality without completely rewriting the code.
ModLogix developers come to the rescue with their angularjs to angular migration strategy. One of the common ideas is to run a hybrid application written in Angular, which then runs an AngularJS application. Additionally, ModLogix provides you with some useful functions and classes that allow us to upgrade and downgrade components, directives, or services so that they can be used in both applications.
Upgrade to AngularJS 1.5+
If our application uses an AngularJS version older than 1.5, we should first upgrade AngularJS to the latest version. With AngularJS 1.5, a number of significant updates have been added to make the migration to Angular easier. The most important of these is the addition of the component() method.
In Angular, almost everything is a component. So after a successful upgrade, the next step is to migrate controllers and some directives to components.
Migrating to TypeScript
The absolute minimum is:
- adding TypeScript compiler to our project,
- changing extensions from .js to .ts,
- migrating components and services to classes.
If we used the ng-app attribute to automatically boot our application, we should switch to manual booting. You can boot the hybrid application manually, so it is a good idea to test how our application will behave after implementing the aforementioned change before starting the migration.
If, so far, our project has not used modules, it is worth implementing them. TypeScript’s compiler allows us to choose from several target modules, i.e., CommonJS, AMD, UMD, System, etc. All we have to do is select the module that suits us, and the TypeScript compiler will generate the code in the appropriate form.
Once our project is ready for migration, we can proceed to install Angular:
The required minimums are:
- @angular/common – necessary services and directives e.g., HttpClient,
- @angular/compiler – templating compiler,
- @angular/core – the core of Angular includes decorators for components, services, and modules, among others,
- @angular/forms – a module essential for implementing forms in Angular. Among other things, it contains. ngModel,
- @angular/platform-browser – module required for DOM and browser work,
- core-js – polyfill for es6,
- rxjs – Reactive JS. Includes observables, for example,
- zone.js – polyfill for zone.js,
- @angular/upgrade – ng-upgrade module.
Once all the required modules are in package.json and in the node_modules directory, we get down to modifying our code responsible for manually booting the application. We replaced the existing code that launched the AngularJS application with code that will launch our hybrid application. Such an application consists of an ngModule, which has no bootstrap property. In the case of a typical application written in Angular, the bootstrap array would include a component, which is the root of our application. Instead, we use the ngDoBootstrap method, which contains the code responsible for manually launching an application written in AngularJS.
To create components in Angular, we use classes and the @Component decorator. The decorator allows you to provide metadata that defines how a component should behave, such as what its template should look like, what CSS styles it should have, what selector it should have, etc.
Migrating a service
When creating a service in Angular, we tag its class with the @Injectable decorator. The decorator makes the class available to the injector.
If we want to use a component, directive, or service written in Angular in code written in AngularJS, we need to downgrade it. Such a scenario can apply to either new components written in Angular or those that have just been migrated. For this, we use the functions – downgradeComponent for components or downgradeInjectable for services.
- If we want to use a component, directive, or service written in AngularJS in code written in Angular, we need to upgrade it. In the case of a component, to achieve this, we create a new directive whose class inherits from the UpgradeComponent class available with the ng-upgrade module and then call the super method in the constructor of this class.
- Migrating from AngularJS to Angular does not only involve migrating the application code itself. In addition to that, we have to face the migration of all kinds of tests we have in our project that use the migrated code. This often involves updating the configuration files that decide how such tests are run, as well as the code of the tests themselves.
- An example of a problem we may encounter when running e2e tests on migrated code is an error with Angular application loading timeouts. This issue can occur if we use the setInterval function in our code.
- We can find many answers on Stackoverflow and on Git Hub to get around the concerns encountered until the protractor code is properly patched.
The process of migrating an application from AngularJS to Angular can be daunting, as it involves many steps before and during the migration itself. However, the benefits of using Angular are well worth the time spent.