| <a href='http://github.com/angular/angular.js/edit/master/docs/content/guide/migration.ngdoc' class='improve-docs btn btn-primary'><i class="glyphicon glyphicon-edit"> </i>Improve this doc</a> |
| |
| |
| <h1 id="migrating-from-1-0-to-1-2">Migrating from 1.0 to 1.2</h1> |
| <p>AngularJS version 1.2 introduces several breaking changes that may require changes to your |
| application's source code.</p> |
| <p>Although we try to avoid breaking changes, there are some cases where it is unavoidable. |
| AngularJS 1.2 has undergone a thorough security review to make applications safer by default, |
| which has driven many of these changes. Several new features, especially animations, would not |
| be possible without a few changes. Finally, some outstanding bugs were best fixed by changing |
| an existing API.</p> |
| <div class="alert alert-warning"> |
| <p><strong>Note:</strong> AngularJS versions 1.1.x are considered "experimental" with breaking changes between minor releases. |
| Version 1.2 is the result of several versions on the 1.1 branch, and has a stable API.</p> |
| |
| <p>If you have an application on 1.1 and want to migrate it to 1.2, everything in the guide |
| below should still apply, but you may want to consult the |
| <a href="https://github.com/angular/angular.js/blob/master/CHANGELOG.md">changelog</a> as well.</p> |
| </div> |
| |
| <ul class="nav nav-list"> |
| <li class="nav-header">Summary of Breaking Changes</li> |
| <li><a href="guide/migration#ngroute-has-been-moved-into-its-own-module">ngRoute has been moved into its own module</a></li> |
| <li><a href="guide/migration#templates-no-longer-automatically-unwrap-promises">Templates no longer automatically unwrap promises</a></li> |
| <li><a href="guide/migration#syntax-for-named-wildcard-parameters-changed-in">Syntax for named wildcard parameters changed in <code>$route</code></a></li> |
| <li><a href="guide/migration#you-can-only-bind-one-expression-to">You can only bind one expression to <code><em>[src]</code>, <code></em>[ng-src]</code> or <code>action</code></a></li> |
| <li><a href="guide/migration#interpolations-inside-dom-event-handlers-are-now-disallowed">Interpolations inside DOM event handlers are now disallowed</a></li> |
| <li><a href="guide/migration#directives-cannot-end-with--start-or--end">Directives cannot end with -start or -end</a></li> |
| <li><a href="guide/migration#in-$q,-promisealways-has-been-renamed-promisefinally">In $q, promise.always has been renamed promise.finally</a></li> |
| <li><a href="guide/migration#ngmobile-is-now-ngtouch">ngMobile is now ngTouch</a></li> |
| <li><a href="guide/migration#resource$then-has-been-removed">resource.$then has been removed</a></li> |
| <li><a href="guide/migration#resource-methods-return-the-promise">Resource methods return the promise</a></li> |
| <li><a href="guide/migration#resource-promises-are-resolved-with-the-resource-instance">Resource promises are resolved with the resource instance</a></li> |
| <li><a href="guide/migration#$locationsearch-supports-multiple-keys">$location.search supports multiple keys</a></li> |
| <li><a href="guide/migration#ngbindhtmlunsafe-has-been-removed-and-replaced-by-ngbindhtml">ngBindHtmlUnsafe has been removed and replaced by ngBindHtml</a></li> |
| <li><a href="guide/migration#form-names-that-are-expressions-are-evaluated">Form names that are expressions are evaluated</a></li> |
| <li><a href="guide/migration#hasownproperty-disallowed-as-an-input-name">hasOwnProperty disallowed as an input name</a></li> |
| <li><a href="guide/migration#directives-order-of-postlink-functions-reversed">Directives: Order of postLink functions reversed</a></li> |
| <li><a href="guide/migration#directive-priority">Directive priority</a></li> |
| <li><a href="guide/migration#ngscenario">ngScenario</a></li> |
| <li><a href="guide/migration#nginclude-and-ngview-replace-its-entire-element-on-update">ngInclude and ngView replace its entire element on update</a></li> |
| <li><a href="guide/migration#urls-are-now-sanitized-against-a-whitelist">URLs are now sanitized against a whitelist</a></li> |
| <li><a href="guide/migration#isolate-scope-only-exposed-to-directives-with-scope-property">Isolate scope only exposed to directives with <code>scope</code> property</a></li> |
| <li><a href="guide/migration#change-to-interpolation-priority">Change to interpolation priority</a></li> |
| <li><a href="guide/migration#underscore-prefixed/suffixed-properties-are-non-bindable">Underscore-prefixed/suffixed properties are non-bindable</a></li> |
| <li><a href="guide/migration#you-cannot-bind-to-select[multiple]">You cannot bind to select[multiple]</a></li> |
| <li><a href="guide/migration#uncommon-region-specific-local-files-were-removed-from-i18n">Uncommon region-specific local files were removed from i18n</a></li> |
| <li><a href="guide/migration#services-can-now-return-functions">Services can now return functions</a></li> |
| <li><a href="guide/migration#modifying-the-dom-outside-digest-cycle">Modifying the DOM outside digest cycle</a></li> |
| </ul> |
| |
| |
| <h2 id="ngroute-has-been-moved-into-its-own-module">ngRoute has been moved into its own module</h2> |
| <p>Just like <code>ngResource</code>, <code>ngRoute</code> is now its own module.</p> |
| <p>Applications that use <code>$route</code>, <code>ngView</code>, and/or <code>$routeParams</code> will now need to load an |
| <code>angular-route.js</code> file and have their application's module dependency on the <code>ngRoute</code> module.</p> |
| <p>Before:</p> |
| <pre><code class="lang-html"><script src="angular.js"></script></code></pre> |
| <pre><code class="lang-javascript">var myApp = angular.module('myApp', ['someOtherModule']);</code></pre> |
| <p>After:</p> |
| <pre><code class="lang-html"><script src="angular.js"></script> |
| <script src="angular-route.js"></script></code></pre> |
| <pre><code class="lang-javascript">var myApp = angular.module('myApp', ['ngRoute', 'someOtherModule']);</code></pre> |
| <p>See <a href="https://github.com/angular/angular.js/commit/5599b55b04788c2e327d7551a4a699d75516dd21">5599b55b</a>.</p> |
| <h2 id="templates-no-longer-automatically-unwrap-promises">Templates no longer automatically unwrap promises</h2> |
| <p><code>$parse</code> and templates in general will no longer automatically unwrap promises.</p> |
| <p>Before:</p> |
| <pre><code class="lang-javascript">$scope.foo = $http({method: 'GET', url: '/someUrl'});</code></pre> |
| <pre><code class="lang-html"><p>{{foo}}</p></code></pre> |
| <p>After:</p> |
| <pre><code class="lang-javascript">$http({method: 'GET', url: '/someUrl'}) |
| .success(function(data) { |
| $scope.foo = data; |
| });</code></pre> |
| <pre><code class="lang-html"><p>{{foo}}</p></code></pre> |
| <p>This feature has been deprecated. If absolutely needed, it can be reenabled for now via the |
| <code>$parseProvider.unwrapPromises(true)</code> API.</p> |
| <p>See <a href="https://github.com/angular/angular.js/commit/5dc35b527b3c99f6544b8cb52e93c6510d3ac577">5dc35b52</a>, |
| <a href="https://github.com/angular/angular.js/commit/b6a37d112b3e1478f4d14a5f82faabf700443748">b6a37d11</a>.</p> |
| <h2 id="syntax-for-named-wildcard-parameters-changed-in-route-">Syntax for named wildcard parameters changed in <code>$route</code></h2> |
| <p>To migrate the code, follow the example below. Here, <code>*highlight</code> becomes <code>:highlight*</code></p> |
| <p>Before:</p> |
| <pre><code class="lang-javascript">$routeProvider.when('/Book1/:book/Chapter/:chapter/*highlight/edit', |
| {controller: noop, templateUrl: 'Chapter.html'});</code></pre> |
| <p>After:</p> |
| <pre><code class="lang-javascript">$routeProvider.when('/Book1/:book/Chapter/:chapter/:highlight*/edit', |
| {controller: noop, templateUrl: 'Chapter.html'});</code></pre> |
| <p>See <a href="https://github.com/angular/angular.js/commit/04cebcc133c8b433a3ac5f72ed19f3631778142b">04cebcc1</a>.</p> |
| <h2 id="you-can-only-bind-one-expression-to-src-ng-src-or-action-">You can only bind one expression to <code>*[src]</code>, <code>*[ng-src]</code> or <code>action</code></h2> |
| <p>With the exception of <code><a></code> and <code><img></code> elements, you cannot bind more than one expression to the |
| <code>src</code> or <code>action</code> attribute of elements.</p> |
| <p>This is one of several improvements to security introduces by Angular 1.2.</p> |
| <p>Concatenating expressions makes it hard to understand whether some combination of concatenated |
| values are unsafe to use and potentially subject to XSS vulnerabilities. To simplify the task of |
| auditing for XSS issues, we now require that a single expression be used for <code>*[src/ng-src]</code> |
| bindings such as bindings for <code>iframe[src]</code>, <code>object[src]</code>, etc. In addition, this requirement is |
| enforced for <code>form</code> tags with <code>action</code> attributes.</p> |
| <table class="table table-bordered code-table"> |
| <thead> |
| <tr> |
| <th>Examples</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td><code><img src="{{a}}/{{b}}"></code></td> |
| <td class="success">ok</td> |
| </tr> |
| <tr> |
| <td><code><iframe src="{{a}}/{{b}}"></iframe></code></td> |
| <td class="error">bad</td> |
| </tr> |
| <tr> |
| <td><code><iframe src="{{a}}"></iframe></code></td> |
| <td class="success">ok</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| |
| <p>To migrate your code, you can combine multiple expressions using a method attached to your scope.</p> |
| <p>Before:</p> |
| <pre><code class="lang-javascript">scope.baseUrl = 'page'; |
| scope.a = 1; |
| scope.b = 2;</code></pre> |
| <pre><code class="lang-html"><!-- Are a and b properly escaped here? Is baseUrl controlled by user? --> |
| <iframe src="{{baseUrl}}?a={{a}&b={{b}}"></code></pre> |
| <p>After:</p> |
| <pre><code class="lang-javascript">var baseUrl = "page"; |
| scope.getIframeSrc = function() { |
| |
| // One should think about their particular case and sanitize accordingly |
| var qs = ["a", "b"].map(function(value, name) { |
| return encodeURIComponent(name) + "=" + |
| encodeURIComponent(value); |
| }).join("&"); |
| |
| // `baseUrl` isn't exposed to a user's control, so we don't have to worry about escaping it. |
| return baseUrl + "?" + qs; |
| };</code></pre> |
| <pre><code class="lang-html"><iframe src="{{getIframeSrc()}}"></code></pre> |
| <p>See <a href="https://github.com/angular/angular.js/commit/38deedd6e3d806eb8262bb43f26d47245f6c2739">38deedd6</a>.</p> |
| <h2 id="interpolations-inside-dom-event-handlers-are-now-disallowed">Interpolations inside DOM event handlers are now disallowed</h2> |
| <p>DOM event handlers execute arbitrary Javascript code. Using an interpolation for such handlers |
| means that the interpolated value is a JS string that is evaluated. Storing or generating such |
| strings is error prone and leads to XSS vulnerabilities. On the other hand, <code>ngClick</code> and other |
| Angular specific event handlers evaluate Angular expressions in non-window (Scope) context which |
| makes them much safer.</p> |
| <p>To migrate the code follow the example below:</p> |
| <p>Before:</p> |
| <pre><code>JS: scope.foo = 'alert(1)'; |
| HTML: <div onclick="{{foo}}"></code></pre> |
| <p>After:</p> |
| <pre><code>JS: scope.foo = function() { alert(1); } |
| HTML: <div ng-click="foo()"></code></pre> |
| <p>See <a href="https://github.com/angular/angular.js/commit/39841f2ec9b17b3b2920fd1eb548d444251f4f56">39841f2e</a>.</p> |
| <h2 id="directives-cannot-end-with-start-or-end">Directives cannot end with -start or -end</h2> |
| <p>This change was necessary to enable multi-element directives. The best fix is to rename existing |
| directives so that they don't end with these suffixes.</p> |
| <p>See <a href="https://github.com/angular/angular.js/commit/e46100f7097d9a8f174bdb9e15d4c6098395c3f2">e46100f7</a>.</p> |
| <h2 id="in-q-promise-always-has-been-renamed-promise-finally">In $q, promise.always has been renamed promise.finally</h2> |
| <p>The reason for this change is to align <code>$q</code> with the <a href="https://github.com/kriskowal/q">Q promise |
| library</a>, despite the fact that this makes it a bit more difficult |
| to use with non-ES5 browsers, like IE8.</p> |
| <p><code>finally</code> also goes well together with the <code>catch</code> API that was added to <code>$q</code> recently and is part |
| of the <a href="http://dom.spec.whatwg.org/">DOM promises standard</a>.</p> |
| <p>To migrate the code follow the example below.</p> |
| <p>Before:</p> |
| <pre><code class="lang-javascript">$http.get('/foo').always(doSomething);</code></pre> |
| <p>After:</p> |
| <pre><code class="lang-javascript">$http.get('/foo').finally(doSomething);</code></pre> |
| <p>Or for IE8-compatible code:</p> |
| <pre><code class="lang-javascript">$http.get('/foo')['finally'](doSomething);</code></pre> |
| <p>See <a href="https://github.com/angular/angular.js/commit/f078762d48d0d5d9796dcdf2cb0241198677582c">f078762d</a>.</p> |
| <h2 id="ngmobile-is-now-ngtouch">ngMobile is now ngTouch</h2> |
| <p>Many touch-enabled devices are not mobile devices, so we decided to rename this module to better |
| reflect its concerns.</p> |
| <p>To migrate, replace all references to <code>ngMobile</code> with <code>ngTouch</code> and <code>angular-mobile.js</code> with |
| <code>angular-touch.js</code>.</p> |
| <p>See <a href="https://github.com/angular/angular.js/commit/94ec84e7b9c89358dc00e4039009af9e287bbd05">94ec84e7</a>.</p> |
| <h2 id="resource-then-has-been-removed">resource.$then has been removed</h2> |
| <p>Resource instances do not have a <code>$then</code> function anymore. Use the <code>$promise.then</code> instead.</p> |
| <p>Before:</p> |
| <pre><code class="lang-javascript">Resource.query().$then(callback);</code></pre> |
| <p>After:</p> |
| <pre><code class="lang-javascript">Resource.query().$promise.then(callback);</code></pre> |
| <p>See <a href="https://github.com/angular/angular.js/commit/05772e15fbecfdc63d4977e2e8839d8b95d6a92d">05772e15</a>.</p> |
| <h2 id="resource-methods-return-the-promise">Resource methods return the promise</h2> |
| <p>Methods of a resource instance return the promise rather than the instance itself.</p> |
| <p>Before:</p> |
| <pre><code class="lang-javascript">resource.$save().chaining = true;</code></pre> |
| <p>After:</p> |
| <pre><code class="lang-javascript">resource.$save(); |
| resource.chaining = true;</code></pre> |
| <p>See <a href="https://github.com/angular/angular.js/commit/05772e15fbecfdc63d4977e2e8839d8b95d6a92d">05772e15</a>.</p> |
| <h2 id="resource-promises-are-resolved-with-the-resource-instance">Resource promises are resolved with the resource instance</h2> |
| <p>On success, the resource promise is resolved with the resource instance rather than HTTP response object.</p> |
| <p>Use interceptor API to access the HTTP response object.</p> |
| <p>Before:</p> |
| <pre><code class="lang-javascript">Resource.query().$then(function(response) {...});</code></pre> |
| <p>After:</p> |
| <pre><code class="lang-javascript">var Resource = $resource('/url', {}, { |
| get: { |
| method: 'get', |
| interceptor: { |
| response: function(response) { |
| // expose response |
| return response; |
| } |
| } |
| } |
| });</code></pre> |
| <p>See <a href="https://github.com/angular/angular.js/commit/05772e15fbecfdc63d4977e2e8839d8b95d6a92d">05772e15</a>.</p> |
| <h2 id="-location-search-supports-multiple-keys">$location.search supports multiple keys</h2> |
| <p><a href="api/ng/service/$location#search"><code>$location.search</code></a> now supports multiple keys with the |
| same value provided that the values are stored in an array.</p> |
| <p>Before this change:</p> |
| <ul> |
| <li><code>parseKeyValue</code> only took the last key overwriting all the previous keys.</li> |
| <li><code>toKeyValue</code> joined the keys together in a comma delimited string.</li> |
| </ul> |
| <p>This was deemed buggy behavior. If your server relied on this behavior then either the server |
| should be fixed, or a simple serialization of the array should be done on the client before |
| passing it to <code>$location</code>.</p> |
| <p>See <a href="https://github.com/angular/angular.js/commit/807394095b991357225a03d5fed81fea5c9a1abe">80739409</a>.</p> |
| <h2 id="ngbindhtmlunsafe-has-been-removed-and-replaced-by-ngbindhtml">ngBindHtmlUnsafe has been removed and replaced by ngBindHtml</h2> |
| <p><code>ngBindHtml</code> which has been moved from <code>ngSanitize</code> module to the core <code>ng</code> module.</p> |
| <p><code>ngBindHtml</code> provides <code>ngBindHtmlUnsafe</code> like |
| behavior (evaluate an expression and innerHTML the result into the DOM) when bound to the result |
| of <code>$sce.trustAsHtml(string)</code>. When bound to a plain string, the string is sanitized via |
| <code>$sanitize</code> before being innerHTML'd. If the <code>$sanitize</code> service isn't available (<code>ngSanitize</code> |
| module is not loaded) and the bound expression evaluates to a value that is not trusted an |
| exception is thrown.</p> |
| <p>See <a href="https://github.com/angular/angular.js/commit/dae694739b9581bea5dbc53522ec00d87b26ae55">dae69473</a>.</p> |
| <h2 id="form-names-that-are-expressions-are-evaluated">Form names that are expressions are evaluated</h2> |
| <p>If you have form names that will evaluate as an expression:</p> |
| <pre><code><form name="ctrl.form"></code></pre> |
| <p>And if you are accessing the form from your controller:</p> |
| <p>Before:</p> |
| <pre><code class="lang-javascript">function($scope) { |
| $scope['ctrl.form'] // form controller instance |
| }</code></pre> |
| <p>After:</p> |
| <pre><code class="lang-javascript">function($scope) { |
| $scope.ctrl.form // form controller instance |
| }</code></pre> |
| <p>This makes it possible to access a form from a controller using the new "controller as" syntax. |
| Supporting the previous behavior offers no benefit.</p> |
| <p>See <a href="https://github.com/angular/angular.js/commit/8ea802a1d23ad8ecacab892a3a451a308d9c39d7">8ea802a1</a>.</p> |
| <h2 id="hasownproperty-disallowed-as-an-input-name">hasOwnProperty disallowed as an input name</h2> |
| <p>Inputs with name equal to <code>hasOwnProperty</code> are not allowed inside form or ngForm directives.</p> |
| <p>Before, inputs whose name was "hasOwnProperty" were quietly ignored and not added to the scope. |
| Now a badname exception is thrown. Using "hasOwnProperty" for an input name would be very unusual |
| and bad practice. To migrate, change your input name.</p> |
| <p>See <a href="https://github.com/angular/angular.js/commit/7a586e5c19f3d1ecc3fefef084ce992072ee7f60">7a586e5c</a>.</p> |
| <h2 id="directives-order-of-postlink-functions-reversed">Directives: Order of postLink functions reversed</h2> |
| <p>The order of postLink fn is now mirror opposite of the order in which corresponding preLinking and compile functions execute.</p> |
| <p>Previously the compile/link fns executed in order, sorted by priority:</p> |
| <table class="table table-bordered table-striped code-table"> |
| <thead> |
| <tr> |
| <th>#</th> |
| <th>Step</th> |
| <th align="center">Old Sort Order</th> |
| <th align="center">New Sort Order</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td>1</td> |
| <td>Compile Fns</td> |
| <td align="center" colspan="2">High → Low</td> |
| </tr> |
| <tr> |
| <td>2</td> |
| <td colspan="3">Compile child nodes</td> |
| </tr> |
| <tr> |
| <td>3</td> |
| <td>PreLink Fns</td> |
| <td align="center" colspan="2">High → Low</td> |
| </tr> |
| <tr> |
| <td>4</td> |
| <td colspan="3">Link child nodes</td> |
| </tr> |
| <tr> |
| <td>5</td> |
| <td>PostLink Fns</td> |
| <td align="center">High → Low</td> |
| <td align="center"><strong>Low → High</strong></td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <p><small>"High → Low" here refers to the <code>priority</code> option of a directive.</small></p> |
| <p>Very few directives in practice rely on the order of postLinking functions (unlike on the order |
| of compile functions), so in the rare case of this change affecting an existing directive, it might |
| be necessary to convert it to a preLinking function or give it negative priority.</p> |
| <p>You can look at <a href="https://github.com/angular/angular.js/commit/31f190d4d53921d32253ba80d9ebe57d6c1de82b">the diff of this |
| commit</a> to see how an internal |
| attribute interpolation directive was adjusted.</p> |
| <p>See <a href="https://github.com/angular/angular.js/commit/31f190d4d53921d32253ba80d9ebe57d6c1de82b">31f190d4</a>.</p> |
| <h2 id="directive-priority">Directive priority</h2> |
| <p>the priority of ngRepeat, ngSwitchWhen, ngIf, ngInclude and ngView has changed. This could affect directives that explicitly specify their priority.</p> |
| <p>In order to make ngRepeat, ngSwitchWhen, ngIf, ngInclude and ngView work together in all common scenarios their directives are being adjusted to achieve the following precedence:</p> |
| <table> |
| <thead> |
| <tr> |
| <th>Directive</th> |
| <th>Old Priority</th> |
| <th>New Priority</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td>ngRepeat</td> |
| <td>1000</td> |
| <td>1000</td> |
| </tr> |
| <tr> |
| <td>ngSwitchWhen</td> |
| <td>500</td> |
| <td>800</td> |
| </tr> |
| <tr> |
| <td>ngIf</td> |
| <td>1000</td> |
| <td>600</td> |
| </tr> |
| <tr> |
| <td>ngInclude</td> |
| <td>1000</td> |
| <td>400</td> |
| </tr> |
| <tr> |
| <td>ngView</td> |
| <td>1000</td> |
| <td>400</td> |
| </tr> |
| </tbody> |
| </table> |
| <p>See <a href="https://github.com/angular/angular.js/commit/b7af76b4c5aa77648cc1bfd49935b48583419023">b7af76b4</a>.</p> |
| <h2 id="ngscenario">ngScenario</h2> |
| <p>browserTrigger now uses an eventData object instead of direct parameters for mouse events. |
| To migrate, place the <code>keys</code>,<code>x</code> and <code>y</code> parameters inside of an object and place that as the |
| third parameter for the browserTrigger function.</p> |
| <p>See <a href="https://github.com/angular/angular.js/commit/28f56a383e9d1ff378e3568a3039e941c7ffb1d8">28f56a38</a>.</p> |
| <h2 id="nginclude-and-ngview-replace-its-entire-element-on-update">ngInclude and ngView replace its entire element on update</h2> |
| <p>Previously <code>ngInclude</code> and <code>ngView</code> only updated its element's content. Now these directives will |
| recreate the element every time a new content is included.</p> |
| <p>This ensures that a single rootElement for all the included contents always exists, which makes |
| definition of css styles for animations much easier.</p> |
| <p>See <a href="https://github.com/angular/angular.js/commit/7d69d52acff8578e0f7d6fe57a6c45561a05b182">7d69d52a</a>, |
| <a href="https://github.com/angular/angular.js/commit/aa2133ad818d2e5c27cbd3933061797096356c8a">aa2133ad</a>.</p> |
| <h2 id="urls-are-now-sanitized-against-a-whitelist">URLs are now sanitized against a whitelist</h2> |
| <p>A whitelist configured via <code>$compileProvider</code> can be used to configure what URLs are considered safe. |
| By default all common protocol prefixes are whitelisted including <code>data:</code> URIs with mime types <code>image/*</code>. |
| This change shouldn't impact apps that don't contain malicious image links.</p> |
| <p>See <a href="https://github.com/angular/angular.js/commit/1adf29af13890d61286840177607edd552a9df97">1adf29af</a>, |
| <a href="https://github.com/angular/angular.js/commit/3e39ac7e1b10d4812a44dad2f959a93361cd823b">3e39ac7e</a>.</p> |
| <h2 id="isolate-scope-only-exposed-to-directives-with-scope-property">Isolate scope only exposed to directives with <code>scope</code> property</h2> |
| <p>If you declare a scope option on a directive, that directive will have an |
| <a href="https://github.com/angular/angular.js/wiki/Understanding-Scopes">isolate scope</a>. In Angular 1.0, if a |
| directive with an isolate scope is used on an element, all directives on that same element have access |
| to the same isolate scope. For example, say we have the following directives:</p> |
| <pre><code>// This directive declares an isolate scope. |
| .directive('isolateScope', function() { |
| return { |
| scope: {}, |
| link: function($scope) { |
| console.log('one = ' + $scope.$id); |
| } |
| }; |
| }) |
| |
| // This directive does not. |
| .directive('nonIsolateScope', function() { |
| return { |
| link: function($scope) { |
| console.log('two = ' + $scope.$id); |
| } |
| }; |
| });</code></pre> |
| <p>Now what happens if we use both directives on the same element?</p> |
| <pre><code><div isolate-scope non-isolate-scope></div></code></pre> |
| <p>In Angular 1.0, the nonIsolateScope directive will have access to the isolateScope directive’s scope. The |
| log statements will print the same id, because the scope is the same. But in Angular 1.2, the nonIsolateScope |
| will not use the same scope as isolateScope. Instead, it will inherit the parent scope. The log statements |
| will print different id’s.</p> |
| <p>If your code depends on the Angular 1.0 behavior (non-isolate directive needs to access state |
| from within the isolate scope), change the isolate directive to use scope locals to pass these explicitly:</p> |
| <p><strong>Before</strong></p> |
| <pre><code><input ng-model="$parent.value" ng-isolate> |
| |
| .directive('ngIsolate', function() { |
| return { |
| scope: {}, |
| template: '{{value}}' |
| }; |
| });</code></pre> |
| <p><strong>After</strong></p> |
| <pre><code><input ng-model="value" ng-isolate> |
| |
| .directive('ngIsolate', function() { |
| return { |
| scope: {value: '=ngModel'}, |
| template: '{{value}} |
| }; |
| });</code></pre> |
| <p>See <a href="https://github.com/angular/angular.js/commit/909cabd36d779598763cc358979ecd85bb40d4d7">909cabd3</a>, |
| <a href="https://github.com/angular/angular.js/issues/1924">#1924</a> and |
| <a href="https://github.com/angular/angular.js/issues/2500">#2500</a>.</p> |
| <h2 id="change-to-interpolation-priority">Change to interpolation priority</h2> |
| <p>Previously, the interpolation priority was <code>-100</code> in 1.2.0-rc.2, and <code>100</code> before 1.2.0-rc.2. |
| Before this change the binding was setup in the post-linking phase.</p> |
| <p>Now the attribute interpolation (binding) executes as a directive with priority 100 and the |
| binding is set up in the pre-linking phase.</p> |
| <p>See <a href="https://github.com/angular/angular.js/commit/79223eae5022838893342c42dacad5eca83fabe8">79223eae</a>, |
| <a href="https://github.com/angular/angular.js/issues/4525">#4525</a>, |
| <a href="https://github.com/angular/angular.js/issues/4528">#4528</a>, and |
| <a href="https://github.com/angular/angular.js/issues/4649">#4649</a></p> |
| <h2 id="underscore-prefixed-suffixed-properties-are-non-bindable">Underscore-prefixed/suffixed properties are non-bindable</h2> |
| <div class="alert alert-info"> |
| <p><strong>Reverted</strong>: This breaking change has been reverted in 1.2.1, and so can be ignored if you're using <strong>version 1.2.1 or higher</strong></p> |
| </div> |
| |
| <p>This change introduces the notion of "private" properties (properties |
| whose names begin and/or end with an underscore) on the scope chain. |
| These properties will not be available to Angular expressions (i.e. {{ |
| }} interpolation in templates and strings passed to <code>$parse</code>) They are |
| freely available to JavaScript code (as before).</p> |
| <p><strong>Motivation</strong></p> |
| <p>Angular expressions execute in a limited context. They do not have |
| direct access to the global scope, <code>window</code>, <code>document</code> or the Function |
| constructor. However, they have direct access to names/properties on |
| the scope chain. It has been a long standing best practice to keep |
| sensitive APIs outside of the scope chain (in a closure or your |
| controller.) That's easier said that done for two reasons:</p> |
| <ol> |
| <li>JavaScript does not have a notion of private properties so if you need |
| someone on the scope chain for JavaScript use, you also expose it to |
| Angular expressions</li> |
| <li>The new <code>controller as</code> syntax that's now in increased usage exposes the |
| entire controller on the scope chain greatly increasing the exposed surface.</li> |
| </ol> |
| <p>Though Angular expressions are written and controlled by the developer, they:</p> |
| <ol> |
| <li>Typically deal with user input</li> |
| <li>Don't get the kind of test coverage that JavaScript code would</li> |
| </ol> |
| <p>This commit provides a way, via a naming convention, to allow restricting properties from |
| controllers/scopes. This means Angular expressions can access only those properties that |
| are actually needed by the expressions.</p> |
| <p>See <a href="https://github.com/angular/angular.js/commit/3d6a89e8888b14ae5cb5640464e12b7811853c7e">3d6a89e8</a>.</p> |
| <h2 id="you-cannot-bind-to-select-multiple-">You cannot bind to select[multiple]</h2> |
| <p>Switching between <code>select[single]</code> and <code>select[multiple]</code> has always been odd due to browser quirks. |
| This feature never worked with two-way data-binding so it's not expected that anyone is using it.</p> |
| <p>If you are interested in properly adding this feature, please submit a pull request on Github.</p> |
| <p>See <a href="https://github.com/angular/angular.js/commit/d87fa0042375b025b98c40bff05e5f42c00af114">d87fa004</a>.</p> |
| <h2 id="uncommon-region-specific-local-files-were-removed-from-i18n">Uncommon region-specific local files were removed from i18n</h2> |
| <p>AngularJS uses the Google Closure library's locale files. The following locales were removed from |
| Closure, so Angular is not able to continue to support them:</p> |
| <p><code>chr</code>, <code>cy</code>, <code>el-polyton</code>, <code>en-zz</code>, <code>fr-rw</code>, <code>fr-sn</code>, <code>fr-td</code>, <code>fr-tg</code>, <code>haw</code>, <code>it-ch</code>, <code>ln-cg</code>, |
| <code>mo</code>, <code>ms-bn</code>, <code>nl-aw</code>, <code>nl-be</code>, <code>pt-ao</code>, <code>pt-gw</code>, <code>pt-mz</code>, <code>pt-st</code>, <code>ro-md</code>, <code>ru-md</code>, <code>ru-ua</code>, |
| <code>sr-cyrl-ba</code>, <code>sr-cyrl-me</code>, <code>sr-cyrl</code>, <code>sr-latn-ba</code>, <code>sr-latn-me</code>, <code>sr-latn</code>, <code>sr-rs</code>, <code>sv-fi</code>, |
| <code>sw-ke</code>, <code>ta-lk</code>, <code>tl-ph</code>, <code>ur-in</code>, <code>zh-hans-hk</code>, <code>zh-hans-mo</code>, <code>zh-hans-sg</code>, <code>zh-hans</code>, |
| <code>zh-hant-hk</code>, <code>zh-hant-mo</code>, <code>zh-hant-tw</code>, <code>zh-hant</code></p> |
| <p>Although these locales were removed from the official AngularJS repository, you can continue to |
| load and use your copy of the locale file provided that you maintain it yourself.</p> |
| <p>See <a href="https://github.com/angular/angular.js/commit/6382e21fb28541a2484ac1a241d41cf9fbbe9d2c">6382e21f</a>.</p> |
| <h2 id="services-can-now-return-functions">Services can now return functions</h2> |
| <p>Previously, the service constructor only returned objects regardless of whether a function was returned.</p> |
| <p>Now, <code>$injector.instantiate</code> (and thus <code>$provide.service</code>) behaves the same as the native |
| <code>new</code> operator and allows functions to be returned as a service.</p> |
| <p>If using a JavaScript preprocessor it's quite possible when upgrading that services could start behaving incorrectly. |
| Make sure your services return the correct type wanted.</p> |
| <p><strong>Coffeescript example</strong></p> |
| <pre><code>myApp.service 'applicationSrvc', -> |
| @something = "value" |
| @someFunct = -> |
| "something else"</code></pre> |
| <p>pre 1.2 this service would return the whole object as the service.</p> |
| <p>post 1.2 this service returns <code>someFunct</code> as the value of the service</p> |
| <p>you would need to change this services to</p> |
| <pre><code>myApp.service 'applicationSrvc', -> |
| @something = "value" |
| @someFunct = -> |
| "something else" |
| return</code></pre> |
| <p>to continue to return the complete instance.</p> |
| <p>See <a href="https://github.com/angular/angular.js/commit/c22adbf160f32c1839fbb35382b7a8c6bcec2927">c22adbf1</a>.</p> |
| |
| |