Angular 4 — The update
Roughly six month after the release of Angular 2, the next big update for Angular is now available: Angular 4, or rather Angular v4, because the team decided it should be called “just Angular” from now on, without stating the version number explicitly in the name. Originally, the “2” was used to differentiate between AngularJS and the all new Angular Framework, which came with many reassessed and refined concepts. The result, Angular, can be used in many different programming Languages like Dart, TypeScript or ECMAScript 5 among others.
When Angular 2 got published, the team also decided to use “semantic versioning” for further versions, making the relationship between different versions in terms of compatibility and new features visible at a glance.
Version numbers are, therefore, set up according to the MAJOR.MINOR.PATCH schema. The particular digit is changed in accordance with the following criteria:
- MAJOR is increased when there is an incompatible change to the API. For Angular, this could be the case if newer versions of a utilized library like zone.js or rxjs gets adopted, that brings along a change to the API.
- MINOR is increased when additional functionality is provided, but existing functions and the API are kept stable. For Angular, this could be something like an additional pipe getting shipped as part of the framework.
- PATCH is increased when some troubleshooting is done without altering the API, thus being backward compatible.
Semantic Versioning in Angular 4
In addition, there is an optional –QUALIFIER specifying a version in a more precise way. For example 4.0.0-rc.1 or 4.0.0 beta would be used to mark a beta version or release candidate.
A jump from 2 to 4. Up next: 8?
Some might have wondered why the version following Angular 2 isn’t Angular 3 but rather “Angular” v4. However, there is a good reason for this: version numbers of all Angular components were to be unified, with the Angular Router having already been developed up to version 3 and consequently had to be upgraded to v4 now. Version 4 was therefore chosen for the entire Angular Framework in the way of unification. Only Angular CLI, the command line tool for project planning and abstraction of build and test execution, has been released as Version 1.0.0.
This is new in Angular 4
The reasons for this new major release are both new features as well as changes incompatible with the previous version. Let’s take a look at the new features:
Router ParamMap
Starting from version 4, it is possible to query a so-called ParamMap in the router, meaning a request for the route- and queryparameter assigned to a route.
Up until now, route parameters were stored in a simple key-value object structure, therefore being accessible by using the standard JavaScript syntax (parameterObjekt[‘parameter-name’] ).
1
2
3
4
5
6
7
8
9
10
11
|
class MyComponent {
sessionId: Observable<string>;
constructor( private route: ActivatedRoute) {}
ngOnInit() {
this .sessionId = this .route
.queryParams
.map(params => params[ 'session_id' ] || 'None' );
}
}
|
Now, the parameters are also available as a map, so you can run them as simple method calls (parameterMap.get(‘parameter-name’)).
1
2
3
4
5
6
7
8
9
10
11
|
class MyComponent {
sessionId: Observable<string>;
constructor( private route: ActivatedRoute) {}
ngOnInit() {
this .sessionId = this .route
.queryParamMap
.map(paramMap => paramMap.get( 'session_id' ) || 'None' );
}
}
|
The utilization as a map also brings advantages in terms of type security. The old key-value structure had an unsafe type (type Params = {[key : string]: any}), whereby the parameter value could take all possible types. With the new map, however, the parameter value is either a string or an array of strings, depending on the method used. Type definition for individual values (ParamMap.get() : string) and type definition for multiple values (ParamMap.getAll() : string[]) apply.
Animations
Functions necessary for animations up until now were provided as part of @angular/core module, implying that these parts of the code were always included in applications, even if they did not get used in apps without animations. To avoid creating bundles with unnecessary large sizes, this function has been put into its own package. (This isn’t just a new feature but also a change making modifications to existing applications necessary if they contain animations.)
Animations are to be provided in the module BrowserAnimationsModule from @angular/platform-browser/animations.
ngIf: Can also be used with “else”
It’s quite a frequent thing to use “conditional rendering” in templates to display information depending on some condition. This is done by using *ngIf. If a condition isn’t met, the corresponding element and all child elements are not added to the DOM-tree. Many times there was also a need for the opposing case, making it necessary to formulate the same condition just the other way around and add another *ngIf.
This has some nasty implications for readability and maintainability of the code – after all, you have to work on multiple lines of code when implementing some changes.
In Angular 4, this use case can be solved with a newly added else. Maybe unexpected for some, Angular uses a separately referenced template fragment, which in the else-case will be used in place of the element marked with *ngIf.
This example illustrates the difference in code between old and new syntax. Use case is to show the user name of a user which is logged in, or a login button for a user not logged in.
Old syntax:
1
2
3
4
5
|
Logged in as {{auth.username}}
Please log in: <button>Login</button>
|
New syntax:
1
2
3
4
5
6
7
8
9
|
<ng-template #needsLogin>
Please log in: <button>Login</button>
</ng-template>
Eingeloggt als {{auth.username}}
|
The functionality of *ngIf in the field of reactive programming got improved when interacting with the async-pipe. It was already possible to “subscribe” (and “unsubscribe”) to asynchronous objects like observables and such from within a template by using the async-Pipe. The new *ngIf-Syntax now makes it possible to also add a local template variable to the result of the if-clause. In the example below the observable, placed inside the variable auth, is resolved by the async-pipe. The result can be used within the template by means of the user variable.
1
2
3
4
5
6
7
8
9
|
<ng-template #loading>
Loading User Data...
</ng-template>
{{user.username }}
|
Note that the async-Pipe is not a necessary precondition for using the new syntax, but rather used for illustrational purposes in this example. Using any other Pipe or no Pipe at all will also work.
Dynamic Components with NgComponentOutlet
The new *ngComponentOutlet-Directive makes it possible to build dynamic components in a declarative way. Up until now, it has been quite a lot of work to build and produce components dynamically at runtime. It’s not enough to just write some HTML code! Angular needs to be notified about the component and add it to the lifecycle, take care of the data binding and change detection. The old way of using ComponentFactory therefore involved relatively much programming work.
The following example shows how that looks like with *ngComponentOutlet:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
@Component ({
selector: ‘app-first-time-visitor’,
template: ‘
<h1>Welcome to our Page!</h1>
’,
})
export class FirstTimeVisitorComponent {}
@Component ({
selector: ‘app-frequent-visitor’,
template: ‘
<h1>Welcome Back!</h1>
’,
})
export class FrequentVisitorComponent {}
@Component ({
selector: ‘app-root',
template: `
<h1>Hello Angular v4!</h1>
<ng-container *ngComponentOutlet= "welcome" ></ng-container>
`,
})
export class App implements OnInit{
welcome = FirstTimeVisitorComponent;
ngOnInit() {
if (! this .user.isfirstVisit){
this .alert = FrequentVisitorComponent;
}
}
}
|
In this example, either FirstTimeVisitorComponent or FrequentVisitorComponent will be displayed as a greeting to visitors, depending on whether they are accessing the page for the first time or have visited it before. The check for prior visits is conducted in the OnInit-Lifecycle-Hook; based on the result, different components are handed over to the template for display.
TypeScript 2.1/2.2
Type security of Angular applications and the speed of ngc-Compiler have been improved – and for that, we need to thank the official support for the most recent TypeScript versions.
StrictNullChecks
Sadly, some parts of the improved Type Checks could not be included in Angular 4 [for now] because some incompatibilities were found in the RC phase. There are plans to include this feature in v4.1, though.
Angular Universal
With Angular Universal, it’s possible to render Angular applications outside of the browser, for instance directly on the web server. With that, JavaScript is no longer necessary for initially rendering the page content, so websites can be optimized better for search engines. Another use case is the utilization of WebWorker Threads to render content outside the GUI Thread. This rendered content can simply be added to the DOM Tree for display later.
For Java developers, the tickets for Spring Framework support [or rather Spring Boot] might be of interest because it adds the option for server side rendering via Nashorn or J2V8:
Unfortunately, no results that could be used in production are available yet. Angular Universal can already be used in different programming languages through node-Runtime.
New Pipe: Title Case
The new titlecase-Pipe will change the first letter of each word to upper case, while all other letters remain in lower case.
Forms get assigned “novalidate” automatically
Up until now, forms had to be marked with “novalidate” if HTML5-validation by the browsers was supposed to be suppressed and full control over the validation was to be given to the Angular application.
Therefore, developers marked all their forms as “novalidate” on a regular basis. Angular 4 will set this attribute automatically.
Source maps also for templates
When it comes to debugging and finding errors, source maps are of vital importance. They show the relation from source code to result and thereby help to narrow down the error. The new Template Compiler will create such source maps also for templates. Therefore there is more contextual information available both when working with the browser debugger and also in Crash-Reports and Log-Messages.
Flat ES-Modules (Flat ESM / FESM)
Instead of many small files that belong to a module, “flat” versions of modules will also be delivered. In this context, flat means that only one file is shipped per module, containing everything belonging to that module. These flat modules are supposed to help with better performance on compiling and on execution in the browser. Furthermore, this shall improve Tree Shaking and Build, so applications will become smaller.
New View Engine for phenomenal speed
From templates and the @Component Elements, Angular generates the View-Layer. In doing so, there are the Just-In-Time Compiler (JIT) and the Ahead-of-Time Compiler (AoT). The JIT is primarily used in development, essentially being an Interpreter. The AoT Compiler generates executable (JavaScript-)Code with embedded HTML fragments from templates and components. This step, often called Codegen, produces a lot of code: Event-Handling, Change-Detection, Data-Binding and handling of dynamic component behaviour will be woven into the result.
Applications generated this way will be very fast but still got a lot of code that slows down the initial launch-time. All that code has to be downloaded first anyway!
The Angular-Team takes a very open approach to this, using other frameworks, for instance the Inferno.js framework, as a reference for performance and design decisions. The different requirements, goals and approaches for the template layer in Angular are also discussed in the extensive design documentation for the View Engine.
As a result, AOT-compiled templates in Angular 4 are substantially smaller, both reducing loading times and at the same time increasing overall page speed through the reduced code size. On average, one can expect a reduction of 60 percent, making for some significant improvement especially on mobile applications.
Additionally, the amount of work to be done by garbage collectors in the browser was reduced, also resulting in some noticeable improvements on performance. The generated code is not just well suited to be packed with classic tools like gzip. It can also be minified with Google Closure Compiler, reducing the size even further.
Necessary adjustments for Angular 4
Let’s take a look at the necessary changes on existing projects to make them work with Angular 4. To facilitate future migrations for developers, the Angular team provides an interactive guide: https://angular-update-guide.firebaseapp.com/. However, since this project is still in its infancy, it should not be used just yet.
Dependencies update
Versions of Angular-Modules can be updated via npm:
npm install @angular/{common,compiler,compiler-cli,core,forms,http,platform-browser,platform-browser-dynamic,platform-server,router,animations}@next –save
Changed lifecycle events
Classes are not allowed to implement Lifecycle Events via inheritance – they need to use Interfaces instead:
Foo extends OnInit
needs to be changed to:
Foo implements OnInit
There won’t be many developers affected by this change, anyway it is rather easy to implement too.
Renaming template tags
Up to now, <template> was used as a Tag or Attribute for Templates. This has been marked as deprecated. It has to be replaced by <ng-template>
Access to Renderer
Renderer and RootRenderer could be used so far but that is not possible anymore. Access is now provided by RendererFactory2.
Use of animations
Animations have been part of Angular Core so far. Because of the separation in Angular 4, imports need to be adjusted when animations are being used.
1
2
3
4
5
6
7
|
import {Component, OnInit} from '@angular/core' ;
import {
animate,
state,
style,
transition,
trigger } from '@angular/animations'
|
In the example, Angular Core still provides “Component” and “OnInit” while “animate”, “state”, “style”, “transition” and “trigger” are now imported from Angular Animations.
News in Angular CLI
Angular CLI is the command line tool that helps developers to comfortably develop, build and test their Angular project. In conjunction with Angular 4, Angular CLI version 1.0.0 was released – it is now a core element of the Angular Project.
A feature especially worth mentioning is the added support for alternative package managers besides npm: it now supports Facebook Yarn and cnpm, for instance.
Usage of Yarn can be activated this way:
ng set –global packageManager=yarn
Angular CLI
Further improvements include the standardized creation of Angular 4 projects by Angular CLI starting from version 1.0.0 and improved error messages while AoT-compiling of templates.
Prospect: Angular 5 and beyond
The world keeps on spinning and Angular keeps pace with it: Further releases are planned as well.
Ongoing work includes a module for ServiceWorker to realize stuff like push-notifications in Angular this way.
The current schedule is set for a new major release every six month. Angular 5 will therefore be ready around this October, Angular 6 should be released in March 2018. In between there will be some minor releases and bug fixes, if necessary – just like it has been since the release of Angular 2. Furthermore, the Angular team decided to do releases at specific time intervals:
- Every week: Patch/bugfix releases
- Every month: Minor release
- Every six month: Major release, with emphasis on easy migration from the prior version
It is important to know that features marked as “deprecated” will be removed in the next release, giving developers six months to migrate if they want to update to the next major version immediately. That is quite recommendable, though, because migration bottlenecks will sooner or later cause problems due to being stuck with an old version. Also, strongly increased effort when migrating over many different versions would be a result.
From feedback they gained from the community, the Angular team learned that the development pace is considered to be “very quick” especially in enterprise environments. To meet the special needs of large organizations, offering a Long-Term-Support (LTS) for Angular is currently being considered, profiting from bugfixes over an extended period.
This might put some project managers’ minds at ease. However, it might still get interesting with regard to the question how upgrades from one LTS version to the next will be facilitated. Speaking from experience, it is rather beneficial to try and keep up with progress and profit from current developments. Furthermore, the exact length of LTS-Support periods for Angular and AngularJS is still being discussed.
Google is using a tool for automated code-migration in-house. There are some discussions going on about whether to release this tool for public use or build something similar for automated migrations and publish that.
This development shows that Angular – partially because they are always ready to listen to the community – grew into a mature and professional framework both suitable for use in small, agile teams as in large organizations.