@@ -13,6 +13,301 @@ which drives many of these changes.
1313* Several new features, especially animations, would not be possible without a few changes.
1414* Finally, some outstanding bugs were best fixed by changing an existing API.
1515
16+ # Migrating from 1.3 to 1.4
17+
18+ Angular 1.4 fixes the major animation issues and introduces some breaking changes for `cookies`, `ngMessages`,
19+ `$compile`, `ngRepeat`, `ngOptions `and some fixes to core filters: `limitTo` and `filter`.
20+
21+ The reason for the ngAnimate refactor was to fix timing issues and to expose new APIs to allow
22+ for developers to construct more versatile animations. We now have access to `$animateCss`
23+ and the many timing-oriented bugs were fixed which resulted in more smoother animations.
24+ If animation is something of interest, then please read over the breaking changes below for animations when
25+ `ngAnimate` is used.
26+
27+ ngMessages has also been upgraded to allow for dynamic message resolution. This handy feature allows for developers
28+ to render error messages with ngMessages that are listed with a directive such as ngRepeat. A great usecase for this
29+ involves pulling error message data from a server and then displaying that data via the mechanics of ngMessages. Be
30+ sure to read the breaking change involved with `ngMessagesInclude` to upgrade your template code.
31+
32+ Other changes, such as the ordering of elements with ngRepeat and ngOptions, may also effect the behavior of your
33+ application. And be sure to also read up on the changes to `$cookies`. The migration jump from 1.3 to 1.4 should be
34+ relatively straightforward otherwise.
35+
36+
37+
38+
39+ ## Animation (`ngAnimate`)
40+
41+ Animation in 1.4 have been refactored internally and the API has stayed much the same. There are, however,
42+ some breaking changes that need to be addressed when any Angular animation code is upgraded to work in 1.4.
43+
44+ Due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
45+ JavaSript and CSS animations can no longer be run in
46+ parallel. With earlier versions of ngAnimate, both CSS and JS animations
47+ would be run together when multiple animations were detected. This
48+ feature has now been removed, however, the same effect, with even more
49+ possibilities, can be achieved by injecting `$animateCss` into a
50+ JavaScript-defined animation and creating custom CSS-based animations
51+ from there.
52+
53+ By using `$animateCss` inside of a JavaScript animation in Angular 1.4, we can trigger custom CSS-based animations
54+ directly from our JavaScript code.
55+
56+ ```js
57+ ngModule.animation('.slide-animation', ['$animateCss', function($animateCss) {
58+ return {
59+ enter: function(element, doneFn) {
60+ // this will trigger a `.ng-enter` and `.ng-enter-active` CSS animation
61+ var animation = $animateCss(element, {
62+ event: 'enter'
63+ // any other CSS-related properties
64+ // addClass: 'some-class',
65+ // removeClass: 'some-other-class',
66+ // from: {},
67+ // to: {}
68+ });
69+
70+ // make sure to read the ngAnimate docs to understand how this works
71+ animation.start().done(doneFn);
72+ }
73+ }
74+ }]);
75+ ```
76+
77+ {@link ngAnimate.$animateCss Click here to learn how to use $animateCss in your animation code}
78+
79+ Due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
80+ animation-related callbacks are now fired on `$animate.on` instead of directly being on the element.
81+
82+ ```js
83+ // < 1.4
84+ element.on('$animate:before', function(e, data) {
85+ if (data.event === 'enter') { ... }
86+ });
87+ element.off('$animate:before', fn);
88+
89+ // 1.4+
90+ $animate.on(element, 'enter', function(data) {
91+ //...
92+ });
93+ $animate.off(element, 'enter', fn);
94+ ```
95+
96+ Due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
97+ the function params for `$animate.enabled()` when an element is used are now flipped. This fix allows
98+ the function to act as a getter when a single element param is provided.
99+
100+ ```js
101+ // < 1.4
102+ $animate.enabled(false, element);
103+
104+ // 1.4+
105+ $animate.enabled(element, false);
106+ ```
107+
108+ Due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
109+ in addition to disabling the children of the element, `$animate.enabled(element, false)` will now also
110+ disable animations on the element itself.
111+
112+ Due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
113+ there is no need to call `$scope.$apply` or `$scope.$digest` inside of a animation promise callback anymore
114+ since the promise is resolved within a digest automatically. (Not to worry, any extra digests will not be
115+ run unless the promise is used.)
116+
117+ ```js
118+ // < 1.4
119+ $animate.enter(element).then(function() {
120+ $scope.$apply(function() {
121+ $scope.explode = true;
122+ });
123+ });
124+
125+ // 1.4+
126+ $animate.enter(element).then(function() {
127+ $scope.explode = true;
128+ });
129+ ```
130+
131+ Due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
132+ when an enter, leave or move animation is triggered then it will always end any pending or active parent
133+ class based animations (animations triggered via ngClass) in order to ensure that any CSS styles are resolved in time.
134+
135+
136+
137+
138+ ## Forms (`ngMessages`, `ngOptions`)
139+
140+ ### ngMessages
141+ The ngMessages module has also been subject to an internal refactor to allow the feature to be more flexible
142+ and compatible with dynamic message data. The ngMessage directive now supports a new attribute called `ng-message-exp`
143+ which will evaluate an expression and will keep track of that expression as it changes in order to re-evaluate
144+ the listed messages.
145+
146+ There is only one breaking change. Please consider the following when including remote message templates via `ng-messages-include`:
147+
148+ Due to [c9a4421f](https://github.com/angular/angular.js/commit/c9a4421fc3c97448527eadef1f42eb2f487ec2e0),
149+ the `ngMessagesInclude` attribute has now been removed and cannot be used in the same element containing
150+ the `ngMessages` directive. Instead, `ngMessagesInclude` is to be used on its own element inline with
151+ other inline messages situated as children within the `ngMessages` container directive.
152+
153+ ```html
154+ <!-- AngularJS 1.3.x -->
155+ <div ng-messages="model.$error" ng-messages-include="remote.html">
156+ <div ng-message="required">Your message is required</div>
157+ </div>
158+
159+ <!-- AngularJS 1.4.x -->
160+ <div ng-messages="model.$error">
161+ <div ng-message="required">Your message is required</div>
162+ <div ng-messages-include="remote.html"></div>
163+ </div>
164+ ```
165+
166+ Depending on where the `ngMessagesInclude` directive is placed it will be prioritized inline with the other messages
167+ before and after it.
168+
169+ ### ngOptions
170+
171+ Due to [7fda214c](https://github.com/angular/angular.js/commit/7fda214c4f65a6a06b25cf5d5aff013a364e9cef),
172+ when `ngOptions` renders the option values within the DOM, the resulting HTML code is different. Normally this
173+ should not affect your application at all, however, if your code relies on inspecing the value property of `<option>`
174+ elements (that `ngOptions` generates) then be sure to read the details
175+ [here](https://github.com/angular/angular.js/commit/7fda214c4f65a6a06b25cf5d5aff013a364e9cef).
176+
177+ Due to [7fda214c](https://github.com/angular/angular.js/commit/7fda214c4f65a6a06b25cf5d5aff013a364e9cef),
178+ when iterating over an object's properties using the `(key, value) in obj` syntax
179+ the order of the elements used to be sorted alphabetically. This was an artificial
180+ attempt to create a deterministic ordering since browsers don't guarantee the order.
181+ But in practice this is not what people want and so this change iterates over properties
182+ in the order they are returned by Object.keys(obj), which is almost always the order
183+ in which the properties were defined.
184+
185+
186+
187+
188+ ## Templating (`ngRepeat`, `$compile`)
189+
190+ ### ngRepeat
191+
192+ Due to [c260e738](https://github.com/angular/angular.js/commit/c260e7386391877625eda086480de73e8a0ba921),
193+ previously, the order of items when using ngRepeat to iterate over object properties was guaranteed to be consistent
194+ by sorting the keys into alphabetic order.
195+
196+ Now, the order of the items is browser dependent based on the order returned
197+ from iterating over the object using the `for key in obj` syntax.
198+
199+ It seems that browsers generally follow the strategy of providing
200+ keys in the order in which they were defined, although there are exceptions
201+ when keys are deleted and reinstated. See
202+ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-browser_issues
203+
204+ The best approach is to convert Objects into Arrays by a filter such as
205+ https://github.com/petebacondarwin/angular-toArrayFilter
206+ or some other mechanism, and then sort them manually in the order you need.
207+
208+
209+ ### $compile
210+
211+ Due to [6a38dbfd](https://github.com/angular/angular.js/commit/6a38dbfd3c34c8f9efff503d17eb3cbeb666d422),
212+ previously, '&' expressions would always set up a function in the isolate scope. Now, if the binding
213+ is marked as optional and the attribute is not specified, no function will be added to the isolate scope.
214+
215+
216+
217+ ## Cookies (`ngCookies`)
218+
219+ Due to [38fbe3ee](https://github.com/angular/angular.js/commit/38fbe3ee8370fc449b82d80df07b5c2ed2cd5fbe),
220+ `$cookies` will no longer expose properties that represent the current browser cookie
221+ values.
222+
223+ The new API on `$cookies` includes:
224+
225+ * `get`
226+ * `put`
227+ * `getObject`
228+ * `putObject`
229+ * `getAll`
230+ * `remove`
231+
232+ The new API no longer polls the browser for changes to the cookies and no longer copy
233+ cookie values onto the `$cookies` object.
234+
235+ The polling is expensive and caused issues with the `$cookies` properties not
236+ synchronizing correctly with the actual browser cookie values.
237+
238+ The reason the polling was originally added was to allow communication between
239+ different tabs, but there are better ways to do this today (for example `localStorage`).
240+
241+ Now you must explictly use the methods above in order to access cookie data. This also means that
242+ you can no longer watch the any properties on `$cookies` for changes to detect for any changes
243+ that occur on the browsers cookies.
244+
245+ This feature is generally only needed if a 3rd party library was programmatically
246+ changing the cookies at runtime. If you rely on this then you must either write code that
247+ can react to the 3rd party library making the changes to cookies or implement your own polling
248+ mechanism.
249+
250+ **DEPRECATION NOTICE**
251+
252+ `$cookieStore` is now deprecated as all the useful logic
253+ has been moved to `$cookies`, to which `$cookieStore` now simply
254+ delegates calls.
255+
256+
257+
258+
259+ ## Server Requests (`$http`)
260+
261+ Due to [5da1256](https://github.com/angular/angular.js/commit/5da1256fc2812d5b28fb0af0de81256054856369),
262+ `transformRequest` functions can no longer modify request headers.
263+
264+ Before this commit `transformRequest` could modify request headers, ex.:
265+
266+ ```javascript
267+ function requestTransform(data, headers) {
268+ headers = angular.extend(headers(), {
269+ 'X-MY_HEADER': 'abcd'
270+ });
271+ }
272+ return angular.toJson(data);
273+ }
274+ ```
275+
276+ This behavior was unintended and undocumented, so the change should affect very few applications. If one
277+ needs to dynamically add / remove headers it should be done in a header function, for example:
278+
279+ ```javascript
280+ $http.get(url, {
281+ headers: {
282+ 'X-MY_HEADER': function(config) {
283+ return 'abcd'; //you've got access to a request config object to specify header value dynamically
284+ }
285+ }
286+ })
287+ ```
288+
289+
290+
291+
292+ ## Filters (`filter`, `limitTo`)
293+
294+ ### `filter` filter
295+ Due to [cea8e751](https://github.com/angular/angular.js/commit/cea8e75144e6910b806b63a6ec2a6d118316fddd),
296+ the `filter` filter will throw an error when a non array. Beforehand it would silently ignore the error
297+ and return an empty array. This is not the behavior anymore.
298+
299+ If necessary, this can be worked around by converting an object to an array,
300+ using a filter such as https://github.com/petebacondarwin/angular-toArrayFilter.
301+
302+ ### `limitTo` filter
303+ Due to [a3c3bf33](https://github.com/angular/angular.js/commit/a3c3bf3332e5685dc319c46faef882cb6ac246e1),
304+ the limitTo filter has changed behavior when the provided limit value is invalid.
305+ Now, instead of returning empty object/array, it returns unchanged input.
306+
307+
308+
309+
310+
16311# Migrating from 1.2 to 1.3
17312
18313## Controllers
0 commit comments