diff --git a/CHANGELOG.md b/CHANGELOG.md index 737b3eed4f76..c5da68b4a5dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,782 @@ + +# 1.7.0-rc.0 maximum-overdrive (2018-04-19) + +## Bug Fixes +- **input:** + - listen on "change" instead of "click" for radio/checkbox ngModels + ([656c8f](https://github.com/angular/angular.js/commit/656c8fa8f23b1277cc5c214c4d0237f3393afa1e), + [#4516](https://github.com/angular/angular.js/issues/4516), + [#14667](https://github.com/angular/angular.js/issues/14667), + [#14685](https://github.com/angular/angular.js/issues/14685)) +- **input\[number\]:** validate min/max against viewValue + ([aa3f95](https://github.com/angular/angular.js/commit/aa3f951330ec7b10b43ea884d9b5754e296770ec), + [#12761](https://github.com/angular/angular.js/issues/12761), + [#16325](https://github.com/angular/angular.js/issues/16325)) +- **jqLite:** make removeData() not remove event handlers + ([b7d396](https://github.com/angular/angular.js/commit/b7d396b8b6e8f27a1f4556d58fc903321e8d532a), + [#15869](https://github.com/angular/angular.js/issues/15869), + [#16512](https://github.com/angular/angular.js/issues/16512)) +- **$compile:** + - remove the preAssignBindingsEnabled flag + ([38f8c9](https://github.com/angular/angular.js/commit/38f8c97af74649ce224b6dd45f433cc665acfbfb), + [#15782](https://github.com/angular/angular.js/issues/15782)) + - add `base[href]` to the list of RESOURCE_URL context attributes + ([1cf728](https://github.com/angular/angular.js/commit/1cf728e209a9e0016068fac2769827e8f747760e), + [#15597](https://github.com/angular/angular.js/issues/15597)) +- **$interval:** throw when trying to cancel non-$interval promise + ([a8bef9](https://github.com/angular/angular.js/commit/a8bef95127775d83d80daa4617c33227c4b443d4), + [#16476](https://github.com/angular/angular.js/issues/16476)) +- **$timeout:** throw when trying to cancel non-$timeout promise + ([336525](https://github.com/angular/angular.js/commit/3365256502344970f86355d3ace1cb4251ae9828), + [#16424](https://github.com/angular/angular.js/issues/16424)) +- **$cookies:** remove the deprecated $cookieStore factory + ([73c646](https://github.com/angular/angular.js/commit/73c6467f1468353215dc689c019ed83aa4993c77), + [#16465](https://github.com/angular/angular.js/issues/16465)) +- **$resource:** fix interceptors and success/error callbacks + ([ea0585](https://github.com/angular/angular.js/commit/ea0585773bb93fd891576e2271254a17e15f1ddd), + [#6731](https://github.com/angular/angular.js/issues/6731), + [#9334](https://github.com/angular/angular.js/issues/9334), + [#6865](https://github.com/angular/angular.js/issues/6865), + [#16446](https://github.com/angular/angular.js/issues/16446)) +- **$templateRequest:** + - give tpload error the correct namespace + ([c617d6](https://github.com/angular/angular.js/commit/c617d6dceee5b000bfceda44ced22fc16b48b18b)) + - always return the template that is stored in the cache + ([fb0099](https://github.com/angular/angular.js/commit/fb00991460cf69ae8bc7f1f826363d09c73c0d5e), + [#16225](https://github.com/angular/angular.js/issues/16225)) +- **$animate:** let cancel() reject the runner promise + ([16b82c](https://github.com/angular/angular.js/commit/16b82c6afe0ab916fef1d6ca78053b00bf5ada83), + [#14204](https://github.com/angular/angular.js/issues/14204), + [#16373](https://github.com/angular/angular.js/issues/16373)) +- **ngTouch:** + - deprecate the module and its contents + ([67f54b](https://github.com/angular/angular.js/commit/67f54b660038de2b4346b3e76d66a8dc8ccb1f9b), + [#16427](https://github.com/angular/angular.js/issues/16427), + [#16431](https://github.com/angular/angular.js/issues/16431)) + - remove ngClick override, `$touchProvider`, and `$touch` + ([11d9ad](https://github.com/angular/angular.js/commit/11d9ad1eb25eaf5967195e424108207427835d50), + [#15761](https://github.com/angular/angular.js/issues/15761), + [#15755](https://github.com/angular/angular.js/issues/15755)) +- **ngScenario:** completely remove the angular scenario runner + ([0cd392](https://github.com/angular/angular.js/commit/0cd39217828b0ad53eaf731576af17d66c18ff60), + [#9405](https://github.com/angular/angular.js/issues/9405)) +- **form:** set $submitted to true on child forms when parent is submitted + ([223de5](https://github.com/angular/angular.js/commit/223de59e988dc0cc8b4ec3a045b7c0735eba1c77), + [#10071](https://github.com/angular/angular.js/issues/10071)) +- **$rootScope:** + - provide correct value of one-time bindings in watchGroup + ([c2b8fa](https://github.com/angular/angular.js/commit/c2b8fab0a480204374d561d6b9b3d47347ac5570)) +- **ngAria:** do not set aria attributes on input[type="hidden"] + ([6d5ef3](https://github.com/angular/angular.js/commit/6d5ef34fc6a974cde73157ba94f9706723dd8f5b), + [#15113](https://github.com/angular/angular.js/issues/15113), + [#16367](https://github.com/angular/angular.js/issues/16367)) +- **ngModel, input:** improve handling of built-in named parsers + ([74b04c](https://github.com/angular/angular.js/commit/74b04c9403af4fc7df5b6420f22c9f45a3e84140), + [#14292](https://github.com/angular/angular.js/issues/14292), + [#10076](https://github.com/angular/angular.js/issues/10076), + [#16347](https://github.com/angular/angular.js/issues/16347)) +- **$httpParamSerializerJQLike:** + - call functions as jQuery does + ([a784fa](https://github.com/angular/angular.js/commit/a784fab605d825f1158c6292b3c42f8c4a502fdf), + [#16138](https://github.com/angular/angular.js/issues/16138), + [#16139](https://github.com/angular/angular.js/issues/16139)) + - follow jQuery for `null` and `undefined` + ([301fdd](https://github.com/angular/angular.js/commit/301fdda648680d89ccab607c413a7ddede7b0165)) +- **$parse:** + - do not pass scope/locals to interceptors of one-time bindings + ([87a586](https://github.com/angular/angular.js/commit/87a586eb9a23cfd0d0bb681cc778b4b8e5c8451d)) + - always pass the intercepted value to watchers + ([2ee503](https://github.com/angular/angular.js/commit/2ee5033967d5f87a516bad137686b0592e25d26b), + [#16021](https://github.com/angular/angular.js/issues/16021)) + - respect the interceptor.$stateful flag + ([de7403](https://github.com/angular/angular.js/commit/de74034ddf6f92505ccdb61be413a6df2c723f87)) +- **Angular:** remove `angular.lowercase` and `angular.uppercase` + ([1daa4f](https://github.com/angular/angular.js/commit/1daa4f2231a89ee88345689f001805ffffa9e7de), + [#15445](https://github.com/angular/angular.js/issues/15445)) +- **$controller:** remove instantiating controllers defined on window + ([e269c1](https://github.com/angular/angular.js/commit/e269c14425a3209040f65c022658770e00a36f16), + [#15349](https://github.com/angular/angular.js/issues/15349), + [#15762](https://github.com/angular/angular.js/issues/15762)) + + +## New Features +- **angular.isArray:** support Array subclasses in `angular.isArray()` + ([e3ece2](https://github.com/angular/angular.js/commit/e3ece2fad9e1e6d47b5f06815ff186d7e6f44948), + [#15533](https://github.com/angular/angular.js/issues/15533), + [#15541](https://github.com/angular/angular.js/issues/15541)) +- **$sce:** handle URL sanitization through the `$sce` service + ([1e9ead](https://github.com/angular/angular.js/commit/1e9eadcd72dbbd5c67dae8328a63e535cfa91ff9)) +- **orderBy:** consider `null` and `undefined` greater than other values + ([1d8046](https://github.com/angular/angular.js/commit/1d804645f7656d592c90216a0355b4948807f6b8), + [#15294](https://github.com/angular/angular.js/issues/15294), + [#16376](https://github.com/angular/angular.js/issues/16376)) +- **$resource:** add support for `request` and `requestError` interceptors (#15674) + ([240a3d](https://github.com/angular/angular.js/commit/240a3ddbf12a9bb79754031be95dae4b6bd2dded), + [#5146](https://github.com/angular/angular.js/issues/5146)) +- **ngModelOptions:** add debounce catch-all + allow debouncing 'default' only + ([55ba44](https://github.com/angular/angular.js/commit/55ba44913e02650b56410aa9ab5eeea5d3492b68), + [#15411](https://github.com/angular/angular.js/issues/15411), + [#16335](https://github.com/angular/angular.js/issues/16335)) +- **$compile:** lower the `xlink:href` security context for SVG's `a` and `image` elements + ([6ccbfa](https://github.com/angular/angular.js/commit/6ccbfa65d60a3dc396d0cf6da21b993ad74653fd), + [#15736](https://github.com/angular/angular.js/issues/15736)) + + +## Performance Improvements +- **$rootScope:** allow $watchCollection use of expression input watching + ([97b00c](https://github.com/angular/angular.js/commit/97b00ca497676aaff8a803762a9f8c7ff4aa24dd)) +- **ngStyle:** use $watchCollection + ([15bbd3](https://github.com/angular/angular.js/commit/15bbd3e18cd89b91f7206a06c73d40e54a8a48a0), + [#15947](https://github.com/angular/angular.js/issues/15947)) +- **$compile:** do not use deepWatch in literal one-way bindings + ([fd4f01](https://github.com/angular/angular.js/commit/fd4f0111188b62773b99ab6eab38b4d2b5d8d727), + [#15301](https://github.com/angular/angular.js/issues/15301)) + + + + +## Breaking Changes + +### **jqLite** due to: + - **[b7d396](https://github.com/angular/angular.js/commit/b7d396b8b6e8f27a1f4556d58fc903321e8d532a)**: make removeData() not remove event handlers + +Before this commit `removeData()` invoked on an element removed its event +handlers as well. If you want to trigger a full cleanup of an element, change: + +```js +elem.removeData(); +``` + +to: + +```js +angular.element.cleanData(elem); +``` + +In most cases, though, cleaning up after an element is supposed to be done +only when it's removed from the DOM as well; in such cases the following: + +```js +elem.remove(); +``` + +will remove event handlers as well. + +### **$cookies** due to: + - **[73c646](https://github.com/angular/angular.js/commit/73c6467f1468353215dc689c019ed83aa4993c77)**: remove the deprecated $cookieStore factory + +The $cookieStore has been removed. Migrate to the $cookies service. Note that +for object values you need to use the `putObject` & `getObject` methods as +`get`/`put` will not correctly save/retrieve them. + +Before: +```js +$cookieStore.put('name', {key: 'value'}); +$cookieStore.get('name'); // {key: 'value'} +$cookieStore.remove('name'); +``` + +After: +```js +$cookies.putObject('name', {key: 'value'}); +$cookies.getObject('name'); // {key: 'value'} +$cookies.remove('name'); +``` + +### **$resource** due to: + - **[ea0585](https://github.com/angular/angular.js/commit/ea0585773bb93fd891576e2271254a17e15f1ddd)**: fix interceptors and success/error callbacks + +If you are not using `success` or `error` callbacks with `$resource`, +your app should not be affected by this change. + +If you are using `success` or `error` callbacks (with or without +response interceptors), one (subtle) difference is that throwing an +error inside the callbacks will not propagate to the returned +`$promise`. Therefore, you should try to use the promises whenever +possible. E.g.: + +```js +// Avoid +User.query(function onSuccess(users) { throw new Error(); }). + $promise. + catch(function onError() { /* Will not be called. */ }); + +// Prefer +User.query(). + $promise. + then(function onSuccess(users) { throw new Error(); }). + catch(function onError() { /* Will be called. */ }); +``` + +Finally, if you are using `success` or `error` callbacks with response +interceptors, the callbacks will now always run _after_ the interceptors +(and wait for them to resolve in case they return a promise). +Previously, the `error` callback was called before the `responseError` +interceptor and the `success` callback was synchronously called after +the `response` interceptor. E.g.: + +```js +var User = $resource('/api/users/:id', {id: '@id'}, { + get: { + method: 'get', + interceptor: { + response: function(response) { + console.log('responseInterceptor-1'); + return $timeout(1000).then(function() { + console.log('responseInterceptor-2'); + return response.resource; + }); + }, + responseError: function(response) { + console.log('responseErrorInterceptor-1'); + return $timeout(1000).then(function() { + console.log('responseErrorInterceptor-2'); + return $q.reject('Ooops!'); + }); + } + } + } +}); +var onSuccess = function(value) { console.log('successCallback', value); }; +var onError = function(error) { console.log('errorCallback', error); }; + +// Assuming the following call is successful... +User.get({id: 1}, onSuccess, onError); + // Old behavior: + // responseInterceptor-1 + // successCallback, {/* Promise object */} + // responseInterceptor-2 + // New behavior: + // responseInterceptor-1 + // responseInterceptor-2 + // successCallback, {/* User object */} + +// Assuming the following call returns an error... +User.get({id: 2}, onSuccess, onError); + // Old behavior: + // errorCallback, {/* Response object */} + // responseErrorInterceptor-1 + // responseErrorInterceptor-2 + // New behavior: + // responseErrorInterceptor-1 + // responseErrorInterceptor-2 + // errorCallback, Ooops! +``` + + - **[240a3d](https://github.com/angular/angular.js/commit/240a3ddbf12a9bb79754031be95dae4b6bd2dded)**: add support for `request` and `requestError` interceptors (#15674) + +Previously, calling a `$resource` method would synchronously call +`$http`. Now, it will be called asynchronously (regardless if a +`request`/`requestError` interceptor has been defined. + +This is not expected to affect applications at runtime, since the +overall operation is asynchronous already, but may affect assertions in +tests. For example, if you want to assert that `$http` has been called +with specific arguments as a result of a `$resource` call, you now need +to run a `$digest` first, to ensure the (possibly empty) request +interceptor promise has been resolved. + +Before: +```js +it('...', function() { + $httpBackend.expectGET('/api/things').respond(...); + var Things = $resource('/api/things'); + Things.query(); + + expect($http).toHaveBeenCalledWith(...); +}); +``` + +After: +```js +it('...', function() { + $httpBackend.expectGET('/api/things').respond(...); + var Things = $resource('/api/things'); + Things.query(); + $rootScope.$digest(); + + expect($http).toHaveBeenCalledWith(...); +}); +``` + +### **$templateRequest**: + - due to **[c617d6](https://github.com/angular/angular.js/commit/c617d6dceee5b000bfceda44ced22fc16b48b18b)**: give tpload error the correct namespace + +Previously the `tpload` error was namespaced to `$compile`. If you have +code that matches errors of the form `[$compile:tpload]` it will no +longer run. You should change the code to match +`[$templateRequest:tpload]`. + + - due to **([fb0099](https://github.com/angular/angular.js/commit/fb00991460cf69ae8bc7f1f826363d09c73c0d5e)**: always return the template that is stored in the cache + +The service now returns the result of `$templateCache.put()` when making a server request to the +template. Previously it would return the content of the response directly. +This now means if you are decorating `$templateCache.put()` to manipulate the template, you will +now get this manipulated result also on the first `$templateRequest` rather than only on subsequent +calls (when the template is retrived from the cache). +In practice this should not affect any apps, as it is unlikely that they rely on the template being +different in the first and subsequent calls. + +### **$animate** due to: + - **[16b82c](https://github.com/angular/angular.js/commit/16b82c6afe0ab916fef1d6ca78053b00bf5ada83)**: let cancel() reject the runner promise + +$animate.cancel(runner) now rejects the underlying +promise and calls the catch() handler on the runner +returned by $animate functions (enter, leave, move, +addClass, removeClass, setClass, animate). +Previously it would resolve the promise as if the animation +had ended successfully. + +Example: + +```js +var runner = $animate.addClass('red'); +runner.then(function() { console.log('success')}); +runner.catch(function() { console.log('cancelled')}); + +runner.cancel(); +``` + +Pre-1.7.0, this logs 'success', 1.7.0 and later it logs 'cancelled'. +To migrate, add a catch() handler to your animation runners. + +### **angular.isArray** due to: + - **[e3ece2](https://github.com/angular/angular.js/commit/e3ece2fad9e1e6d47b5f06815ff186d7e6f44948)**: support Array subclasses in `angular.isArray()` + +Previously, `angular.isArray()` was an alias for `Array.isArray()`. +Therefore, objects that prototypally inherit from `Array` where not +considered arrays. Now such objects are considered arrays too. + +This change affects several other methods that use `angular.isArray()` +under the hood, such as `angular.copy()`, `angular.equals()`, +`angular.forEach()`, and `angular.merge()`. + +This in turn affects how dirty checking treats objects that prototypally +inherit from `Array` (e.g. MobX observable arrays). AngularJS will now +be able to handle these objects better when copying or watching. + +### **$sce** due to: + - **[1e9ead](https://github.com/angular/angular.js/commit/1e9eadcd72dbbd5c67dae8328a63e535cfa91ff9)**: handle URL sanitization through the `$sce` service + +If you use `attrs.$set` for URL attributes (a[href] and img[src]) there will no +longer be any automated sanitization of the value. This is in line with other +programmatic operations, such as writing to the innerHTML of an element. + +If you are programmatically writing URL values to attributes from untrusted +input then you must sanitize it yourself. You could write your own sanitizer or copy +the private `$$sanitizeUri` service. + +Note that values that have been passed through the `$interpolate` service within the +`URL` or `MEDIA_URL` will have already been sanitized, so you would not need to sanitize +these values again. + +### **orderBy** due to: + - **[1d8046](https://github.com/angular/angular.js/commit/1d804645f7656d592c90216a0355b4948807f6b8)**: consider `null` and `undefined` greater than other values + +When using `orderBy` to sort arrays containing `null` values, the `null` values +will be considered "greater than" all other values, except for `undefined`. +Previously, they were sorted as strings. This will result in different (but more +intuitive) sorting order. + +Before: +```js +orderByFilter(['a', undefined, 'o', null, 'z']); +//--> 'a', null, 'o', 'z', undefined +``` + +After: +```js +orderByFilter(['a', undefined, 'o', null, 'z']); +//--> 'a', 'o', 'z', null, undefined +``` + +### **ngScenario** due to: + - **[0cd392](https://github.com/angular/angular.js/commit/0cd39217828b0ad53eaf731576af17d66c18ff60)**: completely remove the angular scenario runner + +The angular scenario runner end-to-end test framework has been +removed from the project and will no longer be available on npm +or bower starting with 1.7.0. +It was deprecated and removed from the documentation in 2014. +Applications that still use it should migrate to +[Protractor](http://www.protractortest.org). +Technically, it should also be possible to continue using an +older version of the scenario runner, as the underlying APIs have +not changed. However, we do not guarantee future compatibility. + +### **form** due to: + - **[223de5](https://github.com/angular/angular.js/commit/223de59e988dc0cc8b4ec3a045b7c0735eba1c77)**: set $submitted to true on child forms when parent is submitted + +Forms will now set $submitted on child forms when they are submitted. +For example: +``` +
+``` + +Submitting this form will set $submitted on "parentform" and "childform". +Previously, it was only set on "parentform". + +This change was introduced because mixing form and ngForm does not create +logically separate forms, but rather something like input groups. +Therefore, child forms should inherit the submission state from their parent form. + +### **ngAria** due to: + - **[6d5ef3](https://github.com/angular/angular.js/commit/6d5ef34fc6a974cde73157ba94f9706723dd8f5b)**: do not set aria attributes on input[type="hidden"] + +ngAria no longer sets aria-* attributes on input[type="hidden"] with ngModel. +This can affect apps that test for the presence of aria attributes on hidden inputs. +To migrate, remove these assertions. +In actual apps, this should not have a user-facing effect, as the previous behavior +was incorrect, and the new behavior is correct for accessibility. + +### **ngModel, input** due to: + - **[74b04c](https://github.com/angular/angular.js/commit/74b04c9403af4fc7df5b6420f22c9f45a3e84140)**: improve handling of built-in named parsers + +*Custom* parsers that fail to parse on input types "email", "url", "number", "date", "month", +"time", "datetime-local", "week", do no longer set `ngModelController.$error[inputType]`, and +the `ng-invalid-[inputType]` class. Also, custom parsers on input type "range" do no +longer set `ngModelController.$error.number` and the `ng-invalid-number` class. + +Instead, any custom parsers on these inputs set `ngModelController.$error.parse` and +`ng-invalid-parse`. This change was made to make distinguishing errors from built-in parsers +and custom parsers easier. + +### **ngModelOptions** due to: + - **[55ba44](https://github.com/angular/angular.js/commit/55ba44913e02650b56410aa9ab5eeea5d3492b68)**: add debounce catch-all + allow debouncing 'default' only + +the 'default' key in 'debounce' now only debounces the default event, i.e. the event +that is added as an update trigger by the different input directives automatically. + +Previously, it also applied to other update triggers defined in 'updateOn' that +did not have a corresponding key in the 'debounce'. + +This behavior is now supported via a special wildcard / catch-all key: '*'. + +See the following example: + +Pre-1.7: +'mouseup' is also debounced by 500 milliseconds because 'default' is applied: +``` +ng-model-options="{ + updateOn: 'default blur mouseup', + debounce: { 'default': 500, 'blur': 0 } +} +``` + +1.7: +The pre-1.7 behavior can be re-created by setting '*' as a catch-all debounce value: +``` +ng-model-options="{ + updateOn: 'default blur mouseup', + debounce: { '*': 500, 'blur': 0 } +} +``` + +In contrast, when only 'default' is used, 'blur' and 'mouseup' are not debounced: +``` +ng-model-options="{ + updateOn: 'default blur mouseup', + debounce: { 'default': 500 } +} +``` + +### **input\[number\]** due to: + - **[aa3f95](https://github.com/angular/angular.js/commit/aa3f951330ec7b10b43ea884d9b5754e296770ec)**: validate min/max against viewValue + +`input[type=number]` with `ngModel` now validates the input for the `max`/`min` restriction against +the `ngModelController.$viewValue` instead of against the `ngModelController.$modelValue`. + +This affects apps that use `$parsers` or `$formatters` to transform the input / model value. + +If you rely on the $modelValue validation, you can overwrite the `min`/`max` validator from a custom directive, as seen in the following example directive definition object: + +``` +{ + restrict: 'A', + require: 'ngModel', + link: function(scope, element, attrs, ctrl) { + var maxValidator = ctrl.$validators.max; + + ctrk.$validators.max = function(modelValue, viewValue) { + return maxValidator(modelValue, modelValue); + }; + } +} +``` + +### **input** due to: + - **[656c8f](https://github.com/angular/angular.js/commit/656c8fa8f23b1277cc5c214c4d0237f3393afa1e)**: listen on "change" instead of "click" for radio/checkbox ngModels + +`input[radio]` and `input[checkbox]` now listen to the "change" event instead of the "click" event. +Most apps should not be affected, as "change" is automatically fired by browsers after "click" +happens. + +Two scenarios might need migration: + +- Custom click events: + +Before this change, custom click event listeners on radio / checkbox would be called after the +input element and `ngModel` had been updated, unless they were specifically registered before +the built-in click handlers. +After this change, they are called before the input is updated, and can call event.preventDefault() +to prevent the input from updating. + +If an app uses a click event listener that expects ngModel to be updated when it is called, it now +needs to register a change event listener instead. + +- Triggering click events: + +Conventional trigger functions: + +The change event might not be fired when the input element is not attached to the document. This +can happen in **tests** that compile input elements and +trigger click events on them. Depending on the browser (Chrome and Safari) and the trigger method, +the change event will not be fired when the input isn't attached to the document. + +Before: + +```js + it('should update the model', inject(function($compile, $rootScope) { + var inputElm = $compile('')($rootScope); + + inputElm[0].click(); // Or different trigger mechanisms, such as jQuery.trigger() + expect($rootScope.checkbox).toBe(true); + }); +``` + +With this patch, `$rootScope.checkbox` might not be true, because the click event +hasn't triggered the change event. To make the test, work append the inputElm to the app's +`$rootElement`, and the `$rootElement` to the `$document`. + +After: + +```js + it('should update the model', inject(function($compile, $rootScope, $rootElement, $document) { + var inputElm = $compile('')($rootScope); + + $rootElement.append(inputElm); + $document.append($rootElement); + + inputElm[0].click(); // Or different trigger mechanisms, such as jQuery.trigger() + expect($rootScope.checkbox).toBe(true); + }); +``` + +`triggerHandler()`: + +If you are using this jQuery / jqLite function on the input elements, you don't have to attach +the elements to the document, but instead change the triggered event to "change". This is because +`triggerHandler(event)` only triggers the exact event when it has been added by jQuery / jqLite. + +### **ngStyle** due to: + - **[15bbd3](https://github.com/angular/angular.js/commit/15bbd3e18cd89b91f7206a06c73d40e54a8a48a0)**: use $watchCollection + +Previously the use of deep watch by ng-style would trigger styles to be +re-applied when nested state changed. Now only changes to direct +properties of the watched object will trigger changes. + +### **$compile** due to: + - **[38f8c9](https://github.com/angular/angular.js/commit/38f8c97af74649ce224b6dd45f433cc665acfbfb)**: remove the preAssignBindingsEnabled flag + +Previously, the `$compileProvider.preAssignBindingsEnabled` flag was supported. +The flag controlled whether bindings were available inside the controller +constructor or only in the `$onInit` hook. The bindings are now no longer +available in the constructor. + +To migrate your code: + +1. If you haven't invoked `$compileProvider.preAssignBindingsEnabled()` you +don't have to do anything to migrate. + +2. If you specified `$compileProvider.preAssignBindingsEnabled(false)`, you +can remove that statement - since AngularJS 1.6.0 this is the default so your +app should still work even in AngularJS 1.6 after such removal. Afterwards, +migrating to AngularJS 1.7.0 shouldn't require any further action. + +3. If you specified `$compileProvider.preAssignBindingsEnabled(true)` you need +to first migrate your code so that the flag can be flipped to `false`. The +instructions on how to do that are available in the "Migrating from 1.5 to 1.6" +guide: +https://docs.angularjs.org/guide/migration#migrating-from-1-5-to-1-6 +Afterwards, remove the `$compileProvider.preAssignBindingsEnabled(true)` +statement. + + - **[6ccbfa](https://github.com/angular/angular.js/commit/6ccbfa65d60a3dc396d0cf6da21b993ad74653fd)**: lower the `xlink:href` security context for SVG's `a` and `image` elements + +In the unlikely case that an app relied on RESOURCE_URL whitelisting for the +purpose of binding to the `xlink:href` property of SVG's `` or `