This article compares the major differences between the the original AngularJS and Angular 2+. If you’re currently stuck with an AngularJS project and not sure whether you should make the jump, this article should help you get started.
In recent years, we’ve seen Angular grow tremendously as a framework and as a platform for developing single page applications (SPAs) and progressive web apps (PWAs). AngularJS was built on top of the idea that declarative programming should be used for building the views. This required decoupling the DOM manipulation from the business logic of the application and the approach had many benefits on its own.
However, AngularJS had many shortcomings in terms of performance and how things worked under the hood. Hence, the development team spent a year rewriting the code from scratch and finally released Angular 2 in late 2016. Most developers felt that Angular 2 was a different platform that had very little resemblance to the original AngularJS.
So let’s compare and contrast AngularJS and Angular 2+.
Frameworks in AngularJS and Angular 2
AngularJS follows the traditional MVC architecture that comprises a model, a view and a controller.
- Controller: the controller represents how user interactions are handled and binds both the model and the view.
- Views: the view represents the presentation layer and the actual UI.
- Model: the model is an abstract representation of your data.
Some developers are of the opinion that AngularJS follows MVVM pattern that replaces the Controller with a View-Model. A View-Model is a JavaScript function that’s similar to that of the controller. What makes it special is that it synchronizes the data between a view and a model. The changes made to a UI element automatically propagate to the model and vice versa.
The following diagram shows how various AngularJS pieces are connected together.
You can read more about AngularJS’s architecture on the official documentation page.
Angular, on the other, hand has a component-based architecture. Every Angular application has at least one component known as the root component. Each component has an associated class that’s responsible for handling the business logic and a template that represents the view layer. Multiple, closely related components can be stacked together to create a module and each module forms a functional unit on its own.
As you can see in the figure, the component is bound to the template. Components are composed using TypeScript classes and templates are attached to them using @Component
annotations. Services can be injected into a component using Angular’s dependency injection subsystem. The concept of modules in Angular is drastically different from that of the AngularJS modules. An NgModule is a container for defining a functional unit. An NgModule can comprise components, services and other functions. The modular unit can then be imported and used with other modules.
All the Angular concepts are better explained at Angular.io.
Templates in AngularJS and Angular 2
In AngularJS the template is written using HTML. To make it dynamic, you can add AngularJS-specific code such as attributes, markups, filters and form controls. In addition, it supports the two-way data binding technique mentioned earlier. The following code snippet demonstrates the use of directives and double curly brackets within the template:
<html ng-app>
<!-- Body tag augmented with ngController directive -->
<body ng-controller="MyController">
<inpu#t ng-model="foo" value="bar">
<!-- Button tag with ngClick directive -->
<!-- Curly bracket is a template binding syntax -->
button ng-click="changeFoo()">{{buttonText}}</button>
<script src="angular.js"></script>
</body>
</html>
In Angular, AngularJS’s template structure was reworked and lots of new features were added to the templates. The primary difference was that each component had a template attached to it. All the HTML elements except <html>
, <body>
, <base>
, and <script>
work within the template. Apart from that, there are features such as template binding, template interpolation, template statements, property binding, event binding and two-way binding. Built-in attribute directives like NgClass, NgStyle and NgModel and built-in structural directives such as NgIf, NgForOf, NgSwitch are also part of the template.
Dependency Injection in AngularJS and Angular 2
Dependency Injection is a design pattern that takes care of satisfying dependencies and injecting them into the components when they’re required. This avoids the need for hardcoding the dependencies into a component. AngularJS has an injector subsystem that’s responsible for creating components, injecting dependencies and resolving the list all dependencies. The following components can be injected on an on-demand basis:
- value
- factory
- service
- provider
- constant
Services, directives and filters can be injected by using a factory method. Here’s an example of a factory method in action. The factory method is registered with a module named myModule
:
angular.module('myModule', [])
.factory('serviceId', ['depService', function(depService) {
// ...
}])
.directive('directiveName', ['depService', function(depService) {
// ...
}])
.filter('filterName', ['depService', function(depService) {
// ...
}]);
Although the approach has stayed the same, Angular has a newer dependency injection system that’s different from that of the older DI pattern. Angular’s dependency injection is managed through the @NgModule
array that comprises providers
and declarations
. The declarations
array is the space where components and directives are declared. Dependencies and services are registered through the providers
array.
Imagine you have a service that retrieves a list of contacts called ContactlistService
and provides it to a ContactList
component. You’d first need to register the ContactlistService
in app.module.ts
inside the providers
array. Next, you’d need to inject the service into the component as follows:
import { Component } from '@angular/core';
import { Contact } from './contact';
import { ContactListService } from './contactlist.service';
@Component({
selector: 'app-contacts-list',
template: `
<div *ngFor="let contact of contacts">
{{contact.id}} - {{contact.name}} - {{contact.number}}
</div>
`
})
export class ContactListComponent {
contacts: Contact[];
constructor(contactlistService: ContactlistService) {
this.contacts = contactlistService.getcontacts();
}
}
Here, we’re telling Angular to inject the service into the component’s constructor.
JavaScript vs TypeScript
AngularJS is a pure JavaScript framework, and models in AngularJS are plain old JavaScript objects. This makes the whole process of setting up the project a lot easier. Any developer with some basic JavaScript experience can get started with the framework. Because of this, Angular 1.0 has a very gentle learning curve compared to that of other front-end frameworks.
Angular 2+ introduced TypeScript as the default language for building applications. TypeScript is a syntactic superset of JavaScript that compiles down to plain JavaScript. The Angular team chose TypeScript over JavaScript because of the type annotation feature that lets you do optional static type checking. Type checking can prevent compile-time errors crawling into your code that would otherwise go unnoticed. This makes your JavaScript code more predictable.
Apart from that, TypeScript is also popular for its classes, interfaces and decorators (class decorators, property decorators and parameter decorators). TypeScript classes are used by Angular for defining components. @Component
is a popular example of how class decorators are used to attach metadata to a component. Usually, this includes component configuration details such as the template selector tag, the templateUrl
and a providers
array so that you can inject any related dependency into that component:
@Component({
selector: 'app-hero-list',
templateUrl: './hero-list.component.html',
providers: [ HeroService ]
})
export class HeroListComponent implements OnInit {
/* . . . */
}
Tooling Support for AngularJS and Angular 2
Better tooling support helps developers build things faster and it adds to the overall development workflow. A command-line interface (CLI) for instance can considerably reduce the amount of time spent creating an application from scratch. Similarly, there are other tools such as IDEs, text editors, test toolkits etc. that help you make development a whole lot easier.
AngularJS didn’t have an official CLI, but there were many third-party generators and tools available. For the IDE, WebStorm and Aptana were the popular choices among the developers. If you’re like me, you could customize a normal text editor like the Submlime Text editor and add the right plugins into it. AngularJS has a browser extension for debugging and testing called ng-inspector. The structure of AngularJS allowed third-party modules to be imported without any hassle. You can find all the popular ng modules at ngmodules.org, which is an open-source project for hosting AngularJS modules.
Angular has more tooling support compared to AngularJS. There’s an official CLI that lets you initialize new projects, serve them and also build optimized bundles for production. You can read more about Angular CLI at GitHub. Because Angular uses TypeScript instead of JavaScript, Visual Studio is supported as an IDE. That’s not all. There are many IDE plugins and independent tools that help you automate and speed up certain aspects of your development cycle. Augury for debugging, NgRev for code analysis, Codelyzer for code validation etc. are pretty useful tools.
Summary
AngularJS had many flaws — most of them related to performance — but it used to be the first go-to choice for rapid prototyping. However, it doesn’t make any sense to go back to AngularJS or maintain an AngularJS project anymore. If you haven’t already made the shift, you should consider doing so.
In this article, we’ve covered the top five differences between AngularJS and Angular 2. Except for the template structure and the approach for dependency injection, almost all other features were revamped. Many of the popular Angular 1.0 features such as controllers, scope, directives, module definition etc. have been replaced with other alternatives. Furthermore, the underlying language has been changed and the structure modified.