AngularJS: Migration process Bitacora
1 2 |
First Step 1.2 -> 1.3 |
We are considering migrate from AJS 1.2.4 to 1.4.7 or 1.4.8, main reason of 1.4+ is because I found it 1.4+ is the most popular and stable these days, and based on the time of release it could be a good idea to update the version.
I found interesting investigate about features we need to cover: from 1.2.4 to 1.4.0 is a big jump. The guide that illustrates migration from 1.2 to 1.3 and 1.3 to 1.4 and then 1.4.1, 1.4.2, 1.4.3, 1.4.4, 1.4.5, 1.4.6, 1.4.7 and finally 1.4.8 based on Angular Documentation.
Here is a brief of that article, common problems we can found migrating the project and dealing with legacy code (most probably from old 1.0 version).
AngularJS Versions we are planning to cover:
Version History
AngularJS 1.5.0 (this version) | 9,638 | Sunday, February 7, 2016 |
AngularJS 1.4.9 | 11,372 | Monday, January 25, 2016 |
AngularJS 1.4.8 | 45,437 | Sunday, November 22, 2015 |
AngularJS 1.4.7 | 42,468 | Tuesday, October 6, 2015 |
AngularJS 1.4.6 | 19,166 | Sunday, September 20, 2015 |
AngularJS 1.4.5 | 19,801 | Sunday, September 6, 2015 |
AngularJS 1.4.4 | 24,026 | Sunday, August 16, 2015 |
AngularJS 1.4.3 | 32,229 | Thursday, July 16, 2015 |
AngularJS 1.4.2 | 13,380 | Tuesday, July 7, 2015 |
AngularJS 1.4.1 | 19,566 | Wednesday, June 17, 2015 |
AngularJS 1.4.0 | 22,461 | Thursday, May 28, 2015 |
Angular JS 1.4.0-rc2 | 1,018 | Thursday, May 14, 2015 |
Angular JS 1.4.0-rc1 | 1,081 | Sunday, April 26, 2015 |
Angular JS 1.4.0-rc0 | 662 | Saturday, April 11, 2015 |
Angular JS 1.4.0-beta6 | 1,288 | Thursday, March 19, 2015 |
Angular JS 1.4.0-beta5 | 822 | Thursday, February 26, 2015 |
Angular JS 1.4.0-beta4 | 717 | Tuesday, February 10, 2015 |
Angular JS 1.4.0-beta3 | 295 | Thursday, February 5, 2015 |
Angular JS 1.4.0-beta1 | 1,252 | Thursday, January 22, 2015 |
AngularJS 1.3.18 | 607 | Sunday, September 6, 2015 |
AngularJS 1.3.17 | 139 | Sunday, September 6, 2015 |
AngularJS 1.3.16 | 1,463 | Sunday, June 7, 2015 |
AngularJS 1.3.15 | 61,888 | Thursday, March 19, 2015 |
AngularJS 1.3.14 | 24,519 | Thursday, February 26, 2015 |
AngularJS 1.3.13 | 26,920 | Tuesday, February 10, 2015 |
AngularJS 1.3.12 | 5,773 | Thursday, February 5, 2015 |
AngularJS 1.3.11 | 217 | Thursday, February 5, 2015 |
AngularJS 1.3.10 | 14,001 | Thursday, January 22, 2015 |
AngularJS 1.3.9 | 4,491 | Saturday, January 17, 2015 |
Angular JS 1.3.8 | 24,905 | Sunday, December 21, 2014 |
Angular JS 1.3.7 | 3,725 | Tuesday, December 16, 2014 |
Angular JS 1.3.6 | 6,062 | Tuesday, December 9, 2014 |
Angular JS 1.3.5 | 5,698 | Wednesday, December 3, 2014 |
Angular JS 1.3.4 | 6,515 | Tuesday, November 25, 2014 |
Angular JS 1.3.3 | 11,579 | Wednesday, November 19, 2014 |
Angular JS 1.3.2 | 9,306 | Sunday, November 9, 2014 |
Angular JS 1.3.1 | 10,885 | Sunday, November 2, 2014 |
Angular JS 1.3.0 | 17,802 | Sunday, October 19, 2014 |
Angular JS 1.3.0-rc5 | 109 | Sunday, October 19, 2014 |
Angular JS 1.3.0-rc4 | 810 | Thursday, October 2, 2014 |
Angular JS 1.3.0-rc3 | 311 | Saturday, September 27, 2014 |
Angular JS 1.3.0-rc2 | 622 | Wednesday, September 17, 2014 |
Angular JS 1.3.0-rc1 | 320 | Thursday, September 11, 2014 |
Angular JS 1.3.0-rc0 | 2,177 | Sunday, August 31, 2014 |
Angular JS 1.3.0-beta9 | 93 | Sunday, May 25, 2014 |
Angular JS 1.3.0-beta8 | 439 | Sunday, May 11, 2014 |
Angular JS 1.3.0-beta7 | 481 | Sunday, April 27, 2014 |
Angular JS 1.3.0-beta6 | 2,150 | Tuesday, April 22, 2014 |
Angular JS 1.3.0-beta5 | 544 | Monday, April 7, 2014 |
Angular JS 1.3.0-beta4 | 272 | Sunday, March 30, 2014 |
Angular JS 1.3.0-beta3 | 727 | Sunday, March 23, 2014 |
Angular JS 1.3.0-beta2 | 167 | Tuesday, March 18, 2014 |
Angular JS 1.3.0-beta1 | 282 | Monday, March 10, 2014 |
Angular JS 1.2.29 | 485 | Tuesday, October 13, 2015 |
Angular JS 1.2.28 | 3,348 | Tuesday, December 16, 2014 |
Angular JS 1.2.27 | 1,184 | Saturday, November 22, 2014 |
Angular JS 1.2.26 | 13,953 | Thursday, October 2, 2014 |
Angular JS 1.2.25 | 13,383 | Wednesday, September 17, 2014 |
Angular JS 1.2.24 | 5,674 | Thursday, September 11, 2014 |
Angular JS 1.2.23 | 18,333 | Sunday, August 24, 2014 |
Angular JS 1.2.22 | 7,928 | Thursday, August 14, 2014 |
Angular JS 1.2.21 | 15,328 | Sunday, July 27, 2014 |
Angular JS 1.2.20 | 9,200 | Wednesday, July 16, 2014 |
Angular JS 1.2.19 | 10,685 | Wednesday, July 2, 2014 |
Angular JS 1.2.18 | 18,069 | Tuesday, June 17, 2014 |
Angular JS 1.2.17 | 10,414 | Sunday, June 8, 2014 |
Angular JS 1.2.16 | 58,145 | Monday, April 7, 2014 |
Angular JS 1.2.15 | 9,047 | Sunday, March 23, 2014 |
Angular JS 1.2.14 | 25,366 | Monday, March 3, 2014 |
Angular JS 1.2.13 | 8,059 | Wednesday, February 19, 2014 |
Angular JS 1.2.12 | 879 | Wednesday, February 19, 2014 |
Angular JS 1.2.11 | 209 | Wednesday, February 19, 2014 |
Angular JS 1.2.10 | 283 | Wednesday, February 19, 2014 |
Angular JS 1.2.9 | 731 | Wednesday, February 19, 2014 |
Version
|
Downloads
|
Last updated
|
---|
Source:
https://code.angularjs.org/
Main Features 1.3 Version:
–Substantial performance and speed improvements: There was a big focus on performance, with a lot of internal optimisations. References to internal benchmarks give some impressive results.
–ES6 Style Promises
–angular-hint: helps us writing better Angular code and makes finding very common mistakes in our code base easier
–One-time bindings syntax
–ngAria
-$http: add xhr statusText to completeRequest callback
–ngMessages: introduce the NgMessages module and directives
–ngModelOptions: custom triggers and debounce of ngModel updates
–ngTouch: add optional ngSwipeDisableMouse attribute to ngSwipe directives to ignore mouse events.
-injector: strict-DI mode which disables automatic function annotation
-$scope: add $watchGroup method for observing a set of expressions
–No IE8 support anymore: IE8 is no longer supported.
To be aware:
-$controller will no longer look for controllers on window (following the Jhon Papa best practices we already cover this)
-You can no longer invoke .bind, .call or .apply on a function in angular expressions.
-The (deprecated) proto property does not work inside angular expressions anymor
-If you need Object.keys, make it accessible in the scope.
–promise unwrapping has been removed: $parseProvider.unwrapPromises and$parseProvider.logPromiseWarnings are gone.
-$interpolate:the function returned by $interpolate no longer has a .parts array set on it.
–angular.copy changes: that it applies the prototype of the original object to the copied object. Previously, angular.copy would copy properties of the original object’s prototype chain directly onto the copied object. This means that if you iterate over only the copied object’s hasOwnProperty properties, it will no longer contain the properties from the prototype.
–forEach: will iterate only over the initial number of items in the array. So if items are added to the array during the iteration, these won’t be iterated over during the initial forEach call.
–angular.toJson: If you expected toJson to strip these types of properties before, you will have to manually do this yourself now.
–jqLite: the jQuery detach() method does not trigger the $destroy event. If you want to destroy Angular data attached to the element, use remove().
-$compile (Directives): The isolated scope of a component directive no longer leaks into the template that contains the instance of the directive. This means that you can no longer access the isolated scope from attributes on the element where the isolated directive is defined, that’s to say, requesting isolate scope and any other scope on a single element is an error.
–ng-pattern: use a regular expression object as the value for the expression.
//before
$scope.exp = ‘/abc/i’;
//after
$scope.exp = /abc/i;
–NgModelController: replace $cancelUpdate() with $rollbackViewValue and has the same meaning
-$broadcast and $emit will now reset the currentScope property of the event to null once the event finished propagating: If any code depends on asynchronously accessing their currentScope property, it should be migrated to use targetScope instead.
–Testing: some deprecated features of Protractor tests no longer work:
Prefixes ng_ and x-ng- are no longer allowed for models
// Before:
var el = element(by.binding(‘{{ foo }}’));
// After:
var el = element(by.binding(‘foo’));
and
//Before:
var el = element(by.binding(‘{{foo}}’));
//After:
var el = element(by.binding(‘foo’));
—
1 |
Second step |
1.3 -> 1.4
Main Features 1.4.0:
The migration jump from 1.3 to 1.4 should be relatively straightforward.
-The new parser is easier to maintain and up to 25% faster
-The whole release has a clear feeling of getting us closer to what an app will look in AngularJS 2, by enforcing some practices.
-bug fixing (around 150)
-Fixes major animation issues
-Introduces a new API for ngCookies
–ngRouter -> UI-router (we are already using it)
–Improved animate: ngAnimate , $animateCss, imperative CSS-based animations, new callback and promises support and anchoring.
–Improved Forms: Dynamic ngMessages
–$cookies service: ngCookies module replaces $cookieStore with the new $cookies service.
var config = {
path: ‘/a/b’,
domain: ‘www.mywebsite.com‘,
expires: new Date(),
secure: true
};
$cookies.put(‘name’, ‘value’, config);
$cookies.putObject(‘name’, ‘value’, config);
$cookies.remove(‘name’, {path: ‘/a/b’});
Handle Objects 1.4+:
–angular.merge:
complements previous angular.copy and angular.extend. It does a deep copy of all properties from source to destination preserving properties in child objects. Note how we can also use multiple source objects that will be merged in order:
// angular.merge syntax (1.4+)
angular.merge(destination, source);
angular.merge(destination, source [, source]);
// 1.4+
var person1 = {
name: ‘John’,
address : {
description: ‘Oxford Street’
}
}
var person2 = {
id: 1,
address : {
postcode: ‘SW1’
}
}
var extended = angular.extend(person1, person2);
var merged = angular.merge(person1, person2);
Result:
//extended object
{
id: 1,
name: ‘John’,
address : {
postcode: ‘SW1’
}
}
// merged object
{
id: 1,
name: ‘John’,
address : {
description: ‘Oxford Street’,
postcode: ‘SW1’
}
}
-limitTo:
filter can now take a second argument to indicate the beginning index, defaulting to 0 if not provided. If the index is negative, it will start from the end:
angular.module(‘limitToApp’, [])
.controller(‘MainCtrl’, function(){
this.letters = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’];
});
Using the limit filter on letters will output the following:
{{vm.letters | limitTo:2}} // [a, b]
{{vm.letters | limitTo:2:0}} // [a, b]
{{vm.letters | limitTo:2:1}} // [b, c]
{{vm.letters | limitTo:2:-1}} // [f]
{{vm.letters | limitTo:-2:-1}} // [d, e]
–ngOptionDisable:
A very old request was the ability to disable an option in a select, and there was no way to do it until this release. Now, you can dynamically specify if an option should be disable
<select ng-model=”modelTest”
ng-options=”customer for customer in customers”>
</select>
//Second fav:
<select ng-model=”secondFav”
ng-options=”customer disable when is modelTest(customer) for customer in customers”>
</select>
–Timezones in date filter:
<p>UTC -> date | date:'short':'UTC'
</p>
<p>Paris -> date | date:'short':'GMT+0200'
</p>
<p>Auckland -> date | date:'short':'GMT+1300'
</p>
-$timeout and $interval:
These two services can now receive additional arguments in their callbacks, to reflect what you can do natively in the browser. So if you want to pass a parameter to the callback function of $interval or $timeout, you can now do:
var sayHello = function(param){
console.log(‘Hello ‘ + param); };
$timeout(sayHello, 1000, true, ‘world!’); // Hello world!
};
Testing:
–ngMock:
A nice addition to the test module are the new methods:
+ they (allowing to repeat a test over a collection of values),
+ tthey (run only this test)
+ xthey (exclude this test).
Examples:
it(“should test with admin”, function(){
var user = admin;
// test with admin
});
it(“should test with user”, function(){
var user = user;
// test with user
});
it(“should test with pass”, function(){
var user = pass;
// test with pass
});
They:
they(“[1] Testing should $prop”, {admin: admin, user: user, pass: pass},
function(user){
// will test 3 times, with user being admin, then user, pass
});
–ngMessageFormat: Internationalization native
-filterFilter: allow array like objects to be filtered
—
1 |
Third step |
1.4.0 -> 1.4.8
1.4.1 Improvements
- $compile:
- workaround for IE11 MutationObserver
- prevent exception when using
watch
as isolated scope binding property in Firefox - assign controller return values correctly for multiple directives
- $location: do not get caught in infinite digest in IE9 when redirecting in
$locationChangeSuccess
- $parse: set null reference properties to
undefined
- $sanitize: do not remove
tabindex
attribute - copy: do not copy the same object twice
- forms: parse exponential notation in
numberInputType
directive - linky: allow case insensitive scheme detection
- ngAria:
- update
aria-valuemin/max
whenmin/max
change - ensure boolean values for aria-hidden and aria-disabled
- update
- ngModel: ignore Object.prototype properties on the form validation object
- $compile: avoid jquery data calls when there is no data
- ngOptions:
- do not watch properties starting with ‘ $ ‘
- use reference check only when not using trackBy
1.4.2 Improvements
- $browser: prevent infinite digest if changing hash when there is no hashPrefix
- $compile:
- throw error when requesting new and isolate scopes (async)
- $location: allow navigating outside the original base URL
- merge: treat dates as atomic values instead of objects.
- ngOptions: only watch numeric properties of an array
- orderBy: ensure correct ordering with arrays of objects and no predicate
- ngAria: add option to disable role=button
1.4.3 Improvements
- $animateCss: ensure animations execute if only a keyframeStyle is provided
- loader: define isFunction (like: angualr.isFunction thing)
- ngAnimate: ensure that orphaned elements do not throw errors when animated
1.4.4 Improvements
- $animate:
- leave animation callback should not overridden by follow-up animation
- make sure to run a post-digest reflow for parentless animations
- ensure that class-based animations are properly applied when cancelled
- $animateCss: make sure that
skipBlocking
avoids the pre-emptive transition-delay styling - $compile:
- don’t trigger $observer if initial value is
undefined
- ignore optional =-bound properties with empty value
- don’t trigger $observer if initial value is
- $injector: Allows ES6 function syntax
- $location: don’t crash if navigating outside the app base
- $q: Use extend to avoid overwriting prototype
- $rootScope: don’t clear phase if $apply is re-entered
- Angular: allow unescaped
=
signs in values inparseKeyValue
- httpParamSerializerJQLike: Follow jQuery for index of arrays of objects
- i18n: by default put negative sign before currency symbol
- injector: check that modulesToLoad isArray.
- input: Firefox validation trigger
- merge: regExp should not be treated as a objects when merging.
- ng/$locale: by default put negative sign before currency symbol
- ngAnimate:
- always apply a preparation reflow for CSS-based animations
- ensure that only string-based addClass/removeClass values are applied
- ensure that parent class-based animations are never closed by their children
- allow animations on body and root elements
- $timeout without invokeApply
- ngCsp: allow CSP to be configurable
- ngModel: correct minErr usage for correct doc creation
- ngOptions: allow empty option selection with multiple attribute
- ngSanitize: escape the wide char quote marks in a regex in linky.js
- $q: small $q performance optimization
- $q when writing tests, there is no need to call
$timeout.flush()
to resolve a call to$q.when
with a value. - ngAnimate: CSS classes added/removed by ngAnimate are now applied synchronously once the first digest has passed.
1.4.5 Improvements
- $animate:
$animate.enabled(false)
should disable animations on $animateCss as well - $animateCss:
- do not throw errors when a closing timeout is fired on a removed element
- fix parse errors on older Android WebViews
- properly handle cancellation timeouts for follow-up animations
- ensure failed animations clear the internal cache
- the transitions options delay value should be applied before class application
- ngAnimate:
- use requestAnimationFrame to space out child animations
- only buffer rAF requests within the animation runners
- ngModel: validate pattern against the viewValue
- ngResources: support IPv6 URLs
1.4.6 Improvements
- $animate: invalid CSS class names should not break subsequent elements
- $browser: handle async updates to location
- $http: propagate status -1 for timed out requests
- $httpBackend: send
null
when post-data is undefined - $parse:
- throw error when accessing a restricted property indirectly
assign
returns the new value
- angular.copy: support copying XML nodes
- form, ngModel: correctly notify parent form when children are added
- input: ignore min/max if they are empty on all input types
- ngAnimateMock: $animate.flush should work for looping animations
- ngAria: clean up tabindex usage
- ngJq: properly detect when
ng-jq
is empty - ngModel:
- remove reference to parentForm from removed control
- let aliased validator directives work on any element
- ngRepeat: add support to iterate an object’s properties even if it does not inherit from Object
- rootScope: add support for watchCollection to watch an object which does not inherit from Object
- select: update option if interpolated value attribute changes
- toDebugString: change replacement string
1.4.8 Bug Fixes
- $animate: ensure leave animation calls
close
callback - $cacheFactory: check key exists before decreasing cache size count
- $compile:
- bind all directive controllers correctly when using
bindToController
- evaluate against the correct scope with bindToController on new scope
- fix scoping of transclusion directives inside replace directive
- bind all directive controllers correctly when using
- $http: apply
transformResponse
even whendata
is empty - $location: ensure
$locationChangeSuccess
fires even if URL ends with#
- $parse: evaluate once simple expressions only once
- $resource: allow XHR request to be cancelled via a timeout promise
- $rootScope: prevent IE9 memory leak when destroying scopes
- Angular.js: fix
isArrayLike
for unusual cases - isArrayLike: handle jQuery objects of length 0
- jqLite:
- deregister special
mouseenter
/mouseleave
events correctly - ensure mouseenter works with svg elements on IE
- deregister special
- limitTo: start at 0 if
begin
is negative and exceeds input length - merge:
- ensure that jqlite->jqlite and DOM->DOM
- clone elements instead of treating them like simple objects
- ngAria: don’t add tabindex to radio and checkbox inputs
- ngInput: change URL_REGEXP to better match RFC3987
- ngMock: reset cache before every test
- ngOptions:
- skip comments and empty options when looking for options
- override select option registration to allow compilation of empty option
Performance Improvements
- $compile: use static jquery data method to avoid creating new instances
- copy:
- avoid regex in
isTypedArray
- only validate/clear if the user specifies a destination
- avoid regex in
- merge: remove unnecessary wrapping of jqLite element
—
Migrating from 1.4.8 to 1.5.0+:
Angular 1.5 takes a big step towards preparing developers for a smoother transition to Angular2 in the future.
Architecturing your applications using components, multi-slot transclusion, one-way bindings in isolate scopes, using lifecycle hooks in directive controllers and relying on native ES6 features.
Because we have no plans to move to Angular 2 maybe this is not an step we want to make.
—
Sources:
If you would like to analyze or read these changes in more detail, please refer to the Google AngularJS changelog and some others IT blogs:
http://angularjs.blogspot.co.uk/
https://docs.angularjs.org/guide/migration#migrating-from-1-3-to-1-4
One Comment
I flirted with the idea of updating one of our older projects from angular 1.2.13 to 1.5 and… bloody hell it’s not worth the trouble. It would take me six months to sort through that shit.