BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage Articles Angular 2 and TypeScript - A High Level Overview

Angular 2 and TypeScript - A High Level Overview

Web Development InfoQ Trends Report

Find out what technologies from the web development space you should keep an eye on this year. Be the innovator in your team and learn more about Vue.js, GraphQl and React. Read the report.

 

AngularJS is by far the most popular JavaScript framework available today for creating web applications. And now Angular 2 and TypeScript are bringing true object oriented web development to the mainstream, in a syntax that is strikingly close to Java 8.

According to Google engineering director Brad Green, 1.3 million developers use AngularJS and 300 thousand are already using the soon to be released Angular 2. After working with Angular 2 for the last 10 months I believe its impact on the JavaScript community will rival that of the Spring framework on Java.

In this article I’ll provide a high-level overview of the Angular 2 framework.

At the end of 2014 Google announced that Angular 2 would be a complete rewrite of AngularJS, and they even created a new language “AtScript” that was meant to be used for writing Angular 2 applications.

But then Microsoft agreed to add support for decorators (a.k.a. annotations) to their TypeScript language (a strict superset of JavaScript), and so that emerged as the language for the development of the Angular 2 framework itself, and the recommended language for developing applications using the AngularJS framework.

You can also develop Angular 2 apps in JavaScript (both ECMAScript 5 and 6) and in Dart.

In addition, the Angular team integrated yet another Microsoft product - the RxJS library of reactive JavaScript extensions, into the Angular 2 framework.

Angular 2 is not an MVC framework, but rather a component-based framework. In Angular 2 an application is a tree of loosely coupled components.

For example, the screenshot below shows the landing page of a sample online auction application that was initially prototyped as a collection of Navbar, Search, Carousel, Product, and Footer components.

The image above illustrates three Product components rendered. The automatic rendering is done by binding the template to the array of components retrieved from the server. The title of each product is a link to the associated product detail page. Since we want to design the auction as a single page application (SPA), we don’t want to refresh the entire page to display product details. Let’s reuse the area currently occupied by the carousel and products, so it can also render product details while keeping the rest of the page unchanged. This task can be accomplished in a few easy steps:

  1. Use Angular’s router-outlet directive, which allows you to declare the area currently occupied by the carousel and products to be <router-outlet> so that it can vary the content based on the user’s navigation.
  2. Encapsulate Carousel and Product inside the Home component
  3. Create a new ProductDetail component
  4. Configure the Angular’s Router to show either the Home or ProductDetail component in the designated <router-outlet> area.

We’ve talked a lot about components, but we have not defined them. In TypeScript a component is simply a class annotated with @Component:

@Component({
  selector: 'auction-home',
  template: `
    HTML or other markup is in-lined here
  `
})
export default class HomeComponent {

 // Application logic goes here
}

The annotation @Component is used to define the component and associated metadata. In this example, the value of the selector property identifies the name of the HTML tag representing this component. The template property is a placeholder for the HTML (or other) markup.

Coming back to our auction landing page, the template of the top level ApplicationComponent might look like this:

This template consists of a mix of standard and custom HTML tags that represent respective components. In the example we in-lined the HTML. If we prefer to store the markup in a separate file (in this case application.html), we’ll would use the property templateURL instead of template, and the code of the ApplicationComponent might look like this:

import {Component} from 'angular2/core';
import {Route, RouteConfig, RouterOutlet} from 'angular2/router';
import HomeComponent from '../home/home';
import NavbarComponent from '../navbar/navbar';
import FooterComponent from '../footer/footer';
import SearchComponent from '../search/search';
import ProductDetailComponent from "../product-detail/product-detail";

@Component({
  selector: 'auction-application',
  templateUrl: 'app/components/application/application.html',
  directives: [
    RouterOutlet,
    NavbarComponent,
    FooterComponent,
    SearchComponent,
    HomeComponent
  ]
})
@RouteConfig([
  {path: '/', component: HomeComponent, as: 'Home'},
  {path: '/products/:id', component: ProductDetailComponent, as: 'ProductDetail'}
])
export default class ApplicationComponent {}

The class ApplicationComponent is annotated with @Component and @RouteConfig (for URL-dependent content). The value of the selector property will be used as a user-defined HTML tag <auction-application>. The templateURL specifies the location of the markup. The section directives includes the RouterOutlet and all child components.

The annotation @RouteConfig configures two routes for the client-side navigation:

  • The content of the route named Home will be rendered by HomeComponent and mapped to the URL fragment /.
  • The content of the route named ProductDetail will be rendered  by ProductDetailComponent and mapped to the URL fragment /product:id.

When the user clicks on a particular product title, the content of the default Home route will be replaced with the content of the ProductDetail route, which provides the value of the parameter id and displays the product details in the <router-outlet> area. For example, the link for navigating to the ProductDetail route, that takes product id 1234 as a parameter, can look as follows:

<a [routerLink]="['/ProductDetail', {'prodId': 1234}]">{{ product.id }}</a>

Dependency Injection

Components use services for implementing business logic. Services are just classes that Angular instantiates and then injects into components.

export class ProductService {
  products: Product[] = [];
  getProducts(): Array<Product> {
    // The code to retrieve product into goes here
    return products;
  }
}

Now if you specify an argument of type ProductService in the HomeComponent constructor, Angular will automatically instantiate and inject that service into the component:

@Component{
 ...
}
export default class HomeComponent {
  products: Product[] = [];

  constructor(productService: ProductService) {
    this.products = productService.getProducts();
  }
}

Angular’s dependency injection module is flexible, and it is easy to use because the objects can be injected only via constructors. Injectors form a hierarchy (each component has an injector), and the injectable object doesn’t have to be an application-level singleton as it might by default in Spring.

Inter-component communications

Component communication can and should be implemented in a loosely coupled manner. A component can declare input and output properties. To pass the data from a parent to a child component, the parent binds the values to the input properties of the child. The child has no need to know who provided the values; it just knows what to do with them.

If a component needs to pass the data to the outside world, it emits the events via the output property. Emits to whom? It’s none of the component’s business. Whoever is interested can create a listener to the custom component’s event.

This mechanism allows us to treat components as black boxes, that can get values in or send data out. I recently recorded a short video you might find useful, illustrating one of the implementations of the Mediator design pattern in Angular 2.

Why TypeScript

TypeScript is a superset of JavaScript but like Java it allows you to define new types. Declaring variables with types rather than the generic var opens the door to new tooling support, which you will find to be a great productivity enhancer. TypeScript comes with a static code analyzer, and as you enter code in your TypeScript-aware IDE (WebStorm/IntelliJ Idea, Visual Studio Code, Sublime Text, etc.) you’re guided by context sensitive help suggesting the available methods in the object or types of the function argument. If you accidentally use an incorrect type, the IDE will highlight the erroneous code. See how WebStorm supports TypeScript here.

Even if your TypeScript application uses a third-party library written in JavaScript, you can install a type definition file (having the extension .d.ts), containing type declarations for this library. Type declarations for hundreds of popular JavaScript libraries are freely available, and you can easily install them with Typings, a TypeScript Definition Manager. Imagine that you want to use jQuery (written in JavaScript) from your TypeScript code. The type-definition files for jQuery will contain declarations (with types) of all jQuery APIs so your IDE can prompt you with which types to use, or highlight any erroneous code.

Performance and Rendering

Rendering performance is substantially improved in Angular 2. Most importantly, the fact that the rendering module is located in a separate module allows you to run the computation-heavy code in a worker thread. Visit the Repaint Rate Challenge Web site to compare the rendering performance of various frameworks. You can feel for yourself the high speed of rendering a large data grid with continuously updating data. Run the test titled "DBMON Angular 2.0 Beta - Web Workers"; a large data grid with constant data refreshes (in a separate thread) is repainted by the browser blazingly fast.

If you ask what Angular 2 features set it apart from other frameworks, first on my list would be this separate module for template rendering and zones:

  • Having the component’s UI declared in separate templates processed by an independent renderer opens up new opportunities in areas from optimization and precompilation of templates, to the ability to create templates for rendering on different devices.
  • The module zone.js monitors the changes in the application and makes decisions on when to update the UI of each component. Any async event triggers the revalidation of the UI in each component and it works amazingly fast.

Note:

While for the majority of applications you won’t need to know the internals of zone.js, if your work on projects requiring fine tuning UI rendering in a complex application, you would be served well to allocate some time to learn more about the zone inner-workings.

Keeping the rendering engine in a separate module allows third-party vendors to replace the default DOM renderer with one that targets non browser-based platforms. For example, this allows reusing the application code across devices, with the UI renderers for mobile devices that use native components. The code of the TypeScript class remains the same, but the content of the @Component annotation will contain XML or another language for rendering native components. A custom Angular 2 renderer is already implemented in the  NativeScript framework, which serves as a bridge between JavaScript and native iOS and Android UI components. With NativeScript you can reuse the component’s code by just replacing the HTML in the template with XML. Another custom UI renderer allows to use Angular 2 with React Native, which is an alternative way of creating native (not hybrid) UI’s for iOS and Android.

Tooling

While the syntax and architecture of Angular 2 applications is a lot easier to understand than AngularJS 1.X, tooling is a bit more complex. This is not surprising; after all you are writing code in one language and deploying it in another, because everything is compiled to JavaScript.

Angular CLI is a project currently in the works that promises to provide a command line interface that will substantially simplify various processes, from initial project generation to production deployment.

Application debugging can be done either in the IDE or in the browser. We use Chrome Developer Tools for debugging. The generated source maps allow you to debug the TypeScript code while the browser runs JavaScript. If you prefer to debug JavaScript, it’s also possible because the TypeScript transpiler generates JavaScript that can be read by humans.

Testing and Deployment

Angular 2 comes with a testing library that allows you to write unit tests in the BDD format. Currently it only supports the Jasmine framework, but additional framework support is on the way. We use Karma test runner, which allows tests to be run against various browsers.

The Protractor framework allows you to write end-to-end tests for your applications. If you monitor the network while loading a simple application in development mode you will see that the browser downloads more than 5Mb (half of that being the TypeScript compiler used by the module loader, SystemJS). But after running deployment and optimization scripts (we use the Webpack bundler), the size of a small app can be as little as 160K (including the Angular 2 framework). We’re looking forward to seeing how Angular CLI will implement production bundling. The Angular team works on offline template compilation, which will lower the framework’s overhead to 50Kb.

Libraries of UI Components

At the time of this writing there are several libraries of the UI components that you can use with Angular 2 applications:

  • PrimeNG - a library of Angular 2 UI components by the creators of PrimeFaces (a popular library used with JavaServer Faces framework).
  • Wijmo 5 - a commercial library of Angular 2 UI components. You have to purchase developer’s licenses to use it.
  • Polymer - a library of nice looking extendable components by Google. At our company we’ve managed to create a pilot Angular 2 app that uses Polymer components, but the integration of the two leaves room for improvement.
  • Material Design 2 - a library of UI components being developed at Google specifically for Angular 2. Currently this library is in early Alpha, but development is pretty active, and I expect to see a couple of dozen well designed UI components in the upcoming three to four months.
  • NG-Lightning - a library of Angular 2 components and directives written from scratch in TypeScript using the Lightning Design System CSS framework.

Is it safe to use Angular 2 in vivo?

Starting from the first Beta release, we are at Farata Systems using Angular 2 for a real world project and have not run into any major issues, at least none that didn’t have a practical workaround.

If you want to be safe, wait a couple more months. Rumor has it that an Angular 2 release candidate will be announced at the Google I/O conference in May of 2016.

What’s in the future

In March of 2016 Brad Green delivered a keynote presentation at the Fluent conference by O’Reilly. Watch the video of this presentation. Are you impressed? I am.

About the Author

Yakov Fain is a New York-based Java Champion and partner at IT consultancy Farata Systems. He leads the Princeton JUG, has authored many articles on software development and several books. Recently he co-authored the book "Angular 2 Development with TypeScript", that will be published by Manning in June of 2016. Yakov often speaks at conferences and teaches Java and Angular 2 classes. He blogs at yakovfain.com.

 

Interested in Angular 2?

More updates: news, deep dives and presentations.

Rate this Article

Adoption
Style

BT