AngularJS 1.6 was just released! Here’s the low down on what to expect for the component method changes as well as
$http Promise method deprecations and the amazing new
ngModelOptions inheritance feature.
Table of contents
The purpose of this article is to focus on the most important changes,
The official documentation guides you through some of the smaller nitty gritty stuff that likely won’t affect you as much.
Component and $onInit
Let’s begin with the most important update and recommendation if you’re using AngularJS 1.5 components and their lifecycle hooks.
When we initialise a particular model on a component’s controller instance, we’d typically do something like this:
Note: here we are not using
$onInit, but can set an Object on a controller, pay attention to this next bit
However, when we switch this to using input
bindings - which is likely the case in a real world application - 1.6 introduces a new change. Let’s assume this:
template will of course render out the Object passed into the binding, however - the
this.applicant log inside the controller will NOT be available. To “fix” this (it’s not essentially a fix though), you’ll need to use
Better yet, use an ES6 class or Typescript:
$onInit guarantees that the
bindings are assigned before using them.
$onInit and ngOnInit
Let’s look at an AngularJS 1.x and Angular v2+ comparison momentarily before we step back to 1.6 as this will add some reason behind this change.
Assume our AngularJS component using an ES6 class:
In Angular, we’d do the following:
This approach treats the
constructor function as the “wiring” of dependencies to be injected, be it AngularJS or Angular. If you’re planning to upgrade your codebase, then adopting this strategy as early as possible is a huge win.
If you’re upgrading to 1.6 and can’t change your entire codebase at once, you can drop in this configuration to enable the bindings back so they work outside
This should really be done as a temporary solution whilst you’re switching things across to
$onInit. Once you’re done making necessary changes, remove the above configuration.
Note: the configuration will be application-wide, so keep this in mind.
$onInit, even if you’re not accepting
bindings. Never put anything, besides public methods on your
A small example to demonstrate what will no longer work in 1.6, and will require
Remember: this change means bindings inside the
constructor, are undefined and now require
A fuller example with bindings and public methods to illustrate (however the bindings could be omitted here and your properties must exist inside
That brings us to the end of
$onInit and the changes you need to consider when migrating and the reasons for doing so.
$http success() and error()
.error() methods have finally been removed - please upgrade your applications to align with the new Promise API.
Refactoring to then()
You’ll potentially have code that looks like this:
Promise would then be returned for a typical
then() callback somewhere in your component’s controller. The success and error methods are deprecated and have been removed.
You’ll need this instead (note everything is contained in the
response argument instead):
Or some ES6 destructuring fun:
Let’s move onto the new
ngModelOptions and inheritance
ngModelOptions allows you to specify how a particular model updates, any debounce on the model setters (which in turns forces a
$digest) and what events you’d like to listen to.
ng-model to update the models on the
default events, such as
input. It also specifies a
debounce to delay model setting. On the
default event, this delay is set to
200 milliseconds - meaning you are not forcing a
$digest every key stroke, but waiting until
200ms after the user has finished the operation. This also ties nicely with backend API requests, as the model will not be set - therefore no request is made every keystroke to the API.
blur is set to
0, meaning we want to ensure the models are changed as soon as a blur occurs, which works nicely with things like validation errors or hitting a backend API.
ngModelOptions is the best performance enhancement you can give your inputs, but when you have multiple
<input> nodes, you end up with something like this:
At which point, it becomes messy very quickly.
This is something I’ve been waiting for in 1.x for too long. Scoped inheritance for
Let’s take a look at that first example and refactor it, as we’re using the same options everywhere:
ngModelwas always able to inherit from an ancestor
ngModelOptionscan now also inherit from an ancestor
Let’s look at
ngModelOptions inheriting from
Control level optional inheritance
We also have the ability to override specific options, whilst inheriting others using
Let’s assume our entire form is going to use the same options, however what we want is to only update our
postcode input on the
'*' uses the wildcard to tell
ngModelOptions to inherit all options from the parent - so you don’t have to keep repeating them but can fine-tune individual inputs. This is extremely powerful and productive.
We can also optionally choose to fallback to
ngModelOptions default values (not the ones specified on the parent container) if we omit the wildcard
$inherit. For example:
ngModelOptions binding will in fact override the entire inheritance chain for that particular input - however it does inherit the
You can obviously mix and match these for your specific use case, but these three examples give you global inheritance, omitted value inheritance and single property inheritance.
Check out the documentation for
ngModelOptionsfor any further information
Migration / changelog
Check the Angular 1.6 migration guide for some of the other noteworthy enhancements (such as the improve
input[type=range] support) - for me these were the big ones to ensure you’re writing your AngularJS applications with the most up-to-date practices.
Huge shout out to Pete Bacon Darwin - lead AngularJS developer - and other collaborators that have been working on this release for so long. Angular 1.x is very much alive and it’s direction is being steered not only towards Angular practices, but better practices in general.