Celebrations: Happy Thanksgiving to all our American readers!
Top features you should know

What’s new in Angular 5?

Karsten Sitterberg
Angular 5
© Shutterstock / Ron Dale

Angular 5 has been released. The 5th edition of the JavaScript framework brings numerous innovations and optimizations. Karsten Sitterberg is taking a closer look at some of the new features and even giving you a sneak peek at what might be in Angular 6.

The update from AngularJS to Angular 2 was a huge step forward, but it was also infamous for not being backwards compatible. In contrast, Angular 4 brought us new features while being backwards compatible. And now, six month later, the latest major release is available.

The upgrade to Angular 5 is an incremental one. This is because many of the changes are done invisibly.

However, some breaking changes have been included, so some developers will still have a lot of work to do. But for all the developers who kept their code bases up-to-date, the changes will be easy to handle this time.

The focus of Angular 5 was to make Angular faster again. The loading time has been improved by smaller bundles. The execution has been improved as well by optimizations at the compiler. For some projects, it is also important to note that the ng-upgrade is still in progress.

This allows AngularJS applications to be migrated smoothly to Angular and vice versa as Angular components can be embedded as downgrades in AngularJS applications.

Additionally, experimental technologies and features can be developed in a special lab space outside the Angular Framework. They can be evaluated and tested by developers at an early stage without negatively affecting the release planning of the framework itself.

SEE MORE: On the road to Angular 5: It’s here!

TypeScript 2.4 support in Angular 5

Angular 5 now officially supports TypeScript version 2.4. Previous versions of Angular have supported TypeScript 2.3 without errors since release 4.3, including the Strict-Null-Check option.

Here’s some of the main features from the latest TypeScript:

String-based enums are a new feature introduced in TypeScript 2.4. This means that the members of an enum can now be expressed with a string instead of a number. Take a look at the example below.

enum Colors {Red = "RED", Green = "GREEN", Blue = "BLUE",}

Note that in this regard string enums cannot be mapped backwards like their number-based relatives. Therefore a query like Colors [“RED”] isn’t possible to catch the string “Red”.

Also, the newer version of TypeScript improves type checking with regards to generics.

On one hand, type checking is becoming generally stricter; on the other hand, the return types of generic functions can now also be inferred. For example, the subsequent call leads to an error:

let foo: Promise<number> = new Promise(resolve => {
    resolve("bar");
    // Error
}); 

Another improvement is the so called Weak-Type-Detection. Types are weak if they only own optional parameters (which can now be detected). Here is an example of this kind of type:

export interface Options {
  showSideNav?: boolean;
  description?: string;
} 

If you try to assign an object that does not have any common property to this kind of weak type, you’ll get a compiler error, as seen in this following code example:

function checkOptions(opts: Options) {
  // ...
}
 
const foo = { showMenu: true };
 
// Error
checkOpts(foo);
 
// Works
checkOpts(foo as Options); 

SEE MORE: 15 reasons why we’re super glad Angular 5 is in our lives

Progressive Web Applications

Currently, the development of progressive web applications (PWA) is an elaborated and complex process. One needs to take care during both development and deployment that neither caching nor the delivery of older versions is impaired.

This changes with Angular 5. The development of progressive web applications should be simplified so much that they can even be created by default. Both users and developers should equally benefit from them.

With Angular-CLI, Angular has the ability to create configuration and code on its own. Essentially, this allows the creation of mobile web applications that have features of native mobile applications, like offline capability, push notifications and an application logo in the start menu of the particular platform. Internally, service workers are used to implement the offline capability of the application and the treatment of push notifications.

Angular provides service workers via the @angular/service-worker module. Other required elements are the generation of the HTML5 caching manifest and the creation of an application shell. Considering the connection status (offline/online) it could be necessary to react to routing events within the application.

The PWA support is activated by the following command:

ng set apps.0.serviceWorker=true 

Build

Even for progressive web applications, updates in the framework are not sufficient; the build tooling has to be extended.

This is exactly what happens with Angular-CLI in other areas. The static analysis of the AOT mode (Ahead of Time Compilation) is already but partly done in the normal build. Thus, many errors are detected earlier at build time and not at runtime.

Thanks to the work on tree shaking, the size of the created application was reduced. The AOT mode has also been accelerated in order to support incremental builds and significantly reduce built time.

For faster builds, a build tool from Google called Bazel can be integrated. However, it’s still in a very early stage of development at the moment. In the future, the Google Closure Compiler can also be used more intensively to achieve more optimized build results.

SEE MORE: Angular vs. React – Who’s one step ahead?

Forms

To improve performance, you can now specify when validators should be executed in forms.

Every time a FormControl value is changed, the validation will be performed accordingly – potentially with every keystroke! In the case of more complex validations, this can lead to a  a noticeably worse performance.

With the new updateOn option, Angular 5 allows you to specify more precisely when this validation should be performed. You can select change, which specifies the previous behavior, submit or blur.

Reactive Forms

In reactive forms, the updateOn property is passed on in the parameter object when the FormControl is instantiated.

Here’s an example of a FormControl with a corresponding parameter object:

this.email = new FormControl(null, { updateOn: 'blur' });

If the validators are also specified, they are specified as properties of the parameter object:

this.email = new FormControl(null, {
  validators: Validators.required,
  updateOn: 'blur'
}); 

Instead of specifying the behavior for all sub-elements on the respective FormControl that is done via FormGroup and FormArray. Take a look at this example of a FormGroup that specifies validation for all contained elements at submit time:

this.login = new FormGroup({
  email: new FormControl(),
  password: new FormControl()
}, { updateOn: 'submit' }); 

The contained elements can override this behavior, as seen below:

this.login = new FormGroup({
  email: new FormControl(null, {
     validators: Validators.required,
     updateOn: 'blur'
  }),
  password: new FormControl(null, [Validators.required])
}, {updateOn: 'submit'}) 

SEE MORE: Angular: One framework

Usage with template-driven forms

For forms that are defined via a template, the updateOn parameter introduced with Angular 5 can also be specified. This is done at ngModelOptions, as shown in the following example:

<input type="email" ngModel [ngModelOptions]="{updateOn: 'submit'}"> 

Here, too, the setting is inherited from the element interleaving in the DOM. In the following example, the setting is made directly in the element of the form:



<form [ngFormOptions]="{updateOn: 'submit'}">
 <input name="email" ngModel type="email">
 <input name="password" ngModel type="email">
</form>



 

A subordinate element can overwrite the default value just as reactive forms can.



<form [ngFormOptions]="{updateOn: 'submit'}">
 <input name="email" ngModel type="email" [ngModelOptions]="{updateOn: 'blur'}">
 <input name="password" ngModel type="email">
</form>



 

HttpClient

The HttpClient introduced with Angular 4.3 now supports a parameter object for headers and parameters. This economizes typing work, as you can see here:

http.get("/api", {
    headers: {
        "X-DEMO-HEADER": "demo"
    },
    params: {
        "foo":  "bar"
    },
}) 

SEE MORE: How to go global: The internationalization of Angular apps

i18N Pipes

The i18n pipes that encompass things like the date, number, currency, and percent have been affected by several changes and internal modifications. For example, the Intl-API previously used by Angular is no longer supported due to browser inconsistencies. Instead, localization is based on the export of data from the Unicode Common Locale Data Repository (CLDR).

These changes represent a break with the API. The default is US-English locale “en-US”. If you need another location or language, you need to import it first. For example, the following code is necessary to import the German locale “de” (equivalent to “de-DE” in the Intl-API) in the AppModule:

import { registerLocaleData } from '@angular/common';
import localeDe from '@angular/common/locales/de';
 
registerLocaleData(localeDe); 

The imported location can now be used as usual:

@NgModule({
  // ...
  providers: [{provide: LOCALE_ID, useValue: 'de'}]
})
export class AppModule{} 

If you are dependent on the existing Intl-Pipes, you can explicitly indicate them (presumably up to the next major version of Angular). For this, however, the old intl API Polyfill and the DeprecatedI18NPipesModule have to be imported ahead of time:

import { NgModule } from '@angular/core';
import { CommonModule, DeprecatedI18NPipesModule } from '@angular/common';
 
@NgModule({
  imports: [
    CommonModule,
       // Import the deprecated module after the CommonModule
    DeprecatedI18NPipesModule
  ]
})
export class AppModule { } 

In addition to the new way of providing locales, a new optional parameter is added to each pipe. With this you can set the LOCALE_ID individually for each pipe.

The different pipes also have other breaks with the API. However, these are mostly limited to new standard values of pipe parameters, such as the number of decimal places after the comma in the percent pipe or the currency symbol inside the currency pipe. These changes are described in detail in the Angular-Changelog here.

Router

The Angular Router has been extended with additional events. Now, for example, you can create progress displays that display when a route is changed. The corresponding events are ActivationStart and ActivationEnd or ChildActivationStart and ChildActivationEnd.

For example, the implementation of a spinner could look like this:

router.events
    // Event = RouteEvent | RouterEvent
    .filter(e => e instanceof RouteEvent)
    .subscribe(e => {
        if (e instanceof ActivationStart) {
            spinner.start();
        } else if (e instanceof ActivationEnd) {
            spinner.end()
        }
    }); 

SEE MORE: Angular IDE for modern web in Eclipse

Animations

The animations package of Angular 5 has been extended with several syntax ingredients. It is now possible to respond to numerical value changes by using :increment and :decrement in order to animate according transitions. Have a look at the code below to see how:

@Component({
    animations: [
        trigger("counter", [ 
            transition(':increment', [ /*...*/ ]),
            transition(':decrement', [ /*...*/ ]),
        ])
    ],
    template: `
    <span [@counter]="count">
    `
})
class MyComponent() { 
    count = 1;
} 

In Angular 5, animations can now be activated and deactivated using values which are associated with data binding. To do this, the .disabled property of the trigger value is bound. See this in action below:

@Component({
    animations: [
        trigger("val", [ /* ... */])
    ],
    template: `


<div [@val]="prop" [@val.disabled]="animationDisabled">
    `
})
class MyComponent() { 
    prop = '';
    animationDisabled = false;
} 

Previously, when animating subordinate elements, it was only possible to limit the selection to a certain number of elements that were counted from the start. Now negative limits are also supported, which refer to the last X elements. Here’s an example showing limiting the last 5 elements with class “person”:

trigger("anim", [
    transition(":enter", [
        query(
            ".person", 
            [ /** ... **/ ],
            { limit: -5 }
        )
    ])
]) 

SEE MORE: Stack Overflow: Java peaks during the 9-5 workday while Angular does better in the evenings

Breaking changes in Angular 5

The following APIs had already been marked as “deprecated” in Angular 4 and have been removed in Angular 5:

  • The OpaqueToken has been removed, instead you have to use InjectionToken now
  • The parameter constructor of the ErrorHandler has been removed.
  • ngOutletContext has been removed from NgTemplateOutlet.
  • The Angular Router takes as values only “enabled” and “disabled” for the parameter initialNavigation. The values “true”, “false”, “legacy_enabled” and “legacy_disabled” are no longer accepted.
  • The ng-container element must now be used instead of i18n comments.
  • The compiler no longer uses the enableLegacyTemplate by default, since in Angular 4 the <template> element was deprecated and <ng-template> should be used instead. The <template> element and the enableLegacyTemplate option will be removed in Angular 6.
  • In favor of the new @angular/common/http module, the angular/http module has been marked as deprecated.
  • The ReflectiveInjector for dependency injection is now deprecated. Instead, the StaticInjector is used. Where ReflectiveInjector.resolveAndCreate was previously used, Injector.create should be used now.

Depending on the project, these changes may create some additionally effort. Generally speaking, however, upgrading to Angular 5 should not evoke a disproportionate amount of effort.

Looking forward to Angular 6

The next major version of Angular is planned for March or April 2018 and shall become the framework version 6. Even though the exact features have yet to be determined, the Angular team already has announced that the latest version’s focus applications should be even faster at runtime and more compact in delivery. Until then, it’s likely that experiments from the Angular-Labs will be stable and adopted into the framework or AngularCL.

I highly recommend switching over to Angular 5. Get the latest version here!

Author

Karsten Sitterberg

Karsten Sitterberg is a freelance developer, trainer and consultant for Java and web technologies. Karsten has a Masters degree in Physics and is an Oracle certified Java developer. He has worked with trion since 2012.


Comments
comments powered by Disqus