11/**
2- * @license AngularJS v1.6.9-build.5530 +sha.07d84dd
2+ * @license AngularJS v1.6.9-build.5546 +sha.ab386cd
33 * (c) 2010-2018 Google, Inc. http://angularjs.org
44 * License: MIT
55 */
@@ -106,7 +106,7 @@ function minErr(module, ErrorConstructor) {
106106 return match;
107107 });
108108
109- message += '\nhttp://errors.angularjs.org/1.6.9-build.5530 +sha.07d84dd /' +
109+ message += '\nhttp://errors.angularjs.org/1.6.9-build.5546 +sha.ab386cd /' +
110110 (module ? module + '/' : '') + code;
111111
112112 for (i = 0, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
@@ -2534,7 +2534,13 @@ function setupModuleLoader(window) {
25342534 * @param {Function} configFn Execute this function on module load. Useful for service
25352535 * configuration.
25362536 * @description
2537- * Use this method to register work which needs to be performed on module loading.
2537+ * Use this method to configure services by injecting their
2538+ * {@link angular.Module#provider `providers`}, e.g. for adding routes to the
2539+ * {@link ngRoute.$routeProvider $routeProvider}.
2540+ *
2541+ * Note that you can only inject {@link angular.Module#provider `providers`} and
2542+ * {@link angular.Module#constant `constants`} into this function.
2543+ *
25382544 * For more about how to configure services, see
25392545 * {@link providers#provider-recipe Provider Recipe}.
25402546 */
@@ -2774,7 +2780,7 @@ function toDebugString(obj, maxDepth) {
27742780var version = {
27752781 // These placeholder strings will be replaced by grunt's `build` task.
27762782 // They need to be double- or single-quoted.
2777- full: '1.6.9-build.5530 +sha.07d84dd ',
2783+ full: '1.6.9-build.5546 +sha.ab386cd ',
27782784 major: 1,
27792785 minor: 6,
27802786 dot: 9,
@@ -2924,7 +2930,7 @@ function publishExternalAPI(angular) {
29242930 });
29252931 }
29262932 ])
2927- .info({ angularVersion: '1.6.9-build.5530 +sha.07d84dd ' });
2933+ .info({ angularVersion: '1.6.9-build.5546 +sha.ab386cd ' });
29282934}
29292935
29302936/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@@ -4578,6 +4584,9 @@ function annotate(fn, strictDi, name) {
45784584 * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the
45794585 * console or not.
45804586 *
4587+ * It is possible to inject other providers into the provider function,
4588+ * but the injected provider must have been defined before the one that requires it.
4589+ *
45814590 * @param {string} name The name of the instance. NOTE: the provider will be available under `name +
45824591 'Provider'` key.
45834592 * @param {(Object|function())} provider If the provider is:
@@ -31524,71 +31533,148 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
3152431533 * For example, if an item is added to the collection, `ngRepeat` will know that all other items
3152531534 * already have DOM elements, and will not re-render them.
3152631535 *
31527- * The default tracking function (which tracks items by their identity) does not allow
31528- * duplicate items in arrays. This is because when there are duplicates, it is not possible
31529- * to maintain a one-to-one mapping between collection items and DOM elements.
31530- *
31531- * If you do need to repeat duplicate items, you can substitute the default tracking behavior
31532- * with your own using the `track by` expression.
31533- *
31534- * For example, you may track items by the index of each item in the collection, using the
31535- * special scope property `$index`:
31536- * ```html
31537- * <div ng-repeat="n in [42, 42, 43, 43] track by $index">
31538- * {{n}}
31539- * </div>
31540- * ```
31541- *
31542- * You may also use arbitrary expressions in `track by`, including references to custom functions
31543- * on the scope:
31544- * ```html
31545- * <div ng-repeat="n in [42, 42, 43, 43] track by myTrackingFunction(n)">
31546- * {{n}}
31547- * </div>
31548- * ```
31536+ * All different types of tracking functions, their syntax, and and their support for duplicate
31537+ * items in collections can be found in the
31538+ * {@link ngRepeat#ngRepeat-arguments ngRepeat expression description}.
3154931539 *
3155031540 * <div class="alert alert-success">
31551- * If you are working with objects that have a unique identifier property, you should track
31552- * by this identifier instead of the object instance. Should you reload your data later, `ngRepeat`
31553- * will not have to rebuild the DOM elements for items it has already rendered, even if the
31554- * JavaScript objects in the collection have been substituted for new ones. For large collections,
31555- * this significantly improves rendering performance. If you don't have a unique identifier,
31556- * `track by $index` can also provide a performance boost .
31541+ * **Best Practice:** If you are working with objects that have a unique identifier property, you
31542+ * should track by this identifier instead of the object instance,
31543+ * e.g. `item in items track by item.id`.
31544+ * Should you reload your data later, `ngRepeat` will not have to rebuild the DOM elements for items
31545+ * it has already rendered, even if the JavaScript objects in the collection have been substituted
31546+ * for new ones. For large collections, this significantly improves rendering performance .
3155731547 * </div>
3155831548 *
31559- * ```html
31560- * <div ng-repeat="model in collection track by model.id">
31561- * {{model.name}}
31562- * </div>
31563- * ```
31549+ * ### Effects of DOM Element re-use
3156431550 *
31565- * <br />
31566- * <div class="alert alert-warning">
31567- * Avoid using `track by $index` when the repeated template contains
31568- * {@link guide/expression#one-time-binding one-time bindings}. In such cases, the `nth` DOM
31569- * element will always be matched with the `nth` item of the array, so the bindings on that element
31570- * will not be updated even when the corresponding item changes, essentially causing the view to get
31571- * out-of-sync with the underlying data.
31572- * </div>
31551+ * When DOM elements are re-used, ngRepeat updates the scope for the element, which will
31552+ * automatically update any active bindings on the template. However, other
31553+ * functionality will not be updated, because the element is not re-created:
3157331554 *
31574- * When no `track by` expression is provided, it is equivalent to tracking by the built-in
31575- * `$id` function, which tracks items by their identity:
31576- * ```html
31577- * <div ng-repeat="obj in collection track by $id(obj)">
31578- * {{obj.prop}}
31579- * </div>
31580- * ```
31555+ * - Directives are not re-compiled
31556+ * - {@link guide/expression#one-time-binding one-time expressions} on the repeated template are not
31557+ * updated if they have stabilized.
3158131558 *
31582- * <br />
31583- * <div class="alert alert-warning">
31584- * **Note:** `track by` must always be the last expression:
31585- * </div>
31586- * ```
31587- * <div ng-repeat="model in collection | orderBy: 'id' as filtered_result track by model.id">
31588- * {{model.name}}
31589- * </div>
31590- * ```
31559+ * The above affects all kinds of element re-use due to tracking, but may be especially visible
31560+ * when tracking by `$index` due to the way ngRepeat re-uses elements.
3159131561 *
31562+ * The following example shows the effects of different actions with tracking:
31563+
31564+ <example module="ngRepeat" name="ngRepeat-tracking" deps="angular-animate.js" animations="true">
31565+ <file name="script.js">
31566+ angular.module('ngRepeat', ['ngAnimate']).controller('repeatController', function($scope) {
31567+ var friends = [
31568+ {name:'John', age:25},
31569+ {name:'Mary', age:40},
31570+ {name:'Peter', age:85}
31571+ ];
31572+
31573+ $scope.removeFirst = function() {
31574+ $scope.friends.shift();
31575+ };
31576+
31577+ $scope.updateAge = function() {
31578+ $scope.friends.forEach(function(el) {
31579+ el.age = el.age + 5;
31580+ });
31581+ };
31582+
31583+ $scope.copy = function() {
31584+ $scope.friends = angular.copy($scope.friends);
31585+ };
31586+
31587+ $scope.reset = function() {
31588+ $scope.friends = angular.copy(friends);
31589+ };
31590+
31591+ $scope.reset();
31592+ });
31593+ </file>
31594+ <file name="index.html">
31595+ <div ng-controller="repeatController">
31596+ <ol>
31597+ <li>When you click "Update Age", only the first list updates the age, because all others have
31598+ a one-time binding on the age property. If you then click "Copy", the current friend list
31599+ is copied, and now the second list updates the age, because the identity of the collection items
31600+ has changed and the list must be re-rendered. The 3rd and 4th list stay the same, because all the
31601+ items are already known according to their tracking functions.
31602+ </li>
31603+ <li>When you click "Remove First", the 4th list has the wrong age on both remaining items. This is
31604+ due to tracking by $index: when the first collection item is removed, ngRepeat reuses the first
31605+ DOM element for the new first collection item, and so on. Since the age property is one-time
31606+ bound, the value remains from the collection item which was previously at this index.
31607+ </li>
31608+ </ol>
31609+
31610+ <button ng-click="removeFirst()">Remove First</button>
31611+ <button ng-click="updateAge()">Update Age</button>
31612+ <button ng-click="copy()">Copy</button>
31613+ <br><button ng-click="reset()">Reset List</button>
31614+ <br>
31615+ <code>track by $id(friend)</code> (default):
31616+ <ul class="example-animate-container">
31617+ <li class="animate-repeat" ng-repeat="friend in friends">
31618+ {{friend.name}} is {{friend.age}} years old.
31619+ </li>
31620+ </ul>
31621+ <code>track by $id(friend)</code> (default), with age one-time binding:
31622+ <ul class="example-animate-container">
31623+ <li class="animate-repeat" ng-repeat="friend in friends">
31624+ {{friend.name}} is {{::friend.age}} years old.
31625+ </li>
31626+ </ul>
31627+ <code>track by friend.name</code>, with age one-time binding:
31628+ <ul class="example-animate-container">
31629+ <li class="animate-repeat" ng-repeat="friend in friends track by friend.name">
31630+ {{friend.name}} is {{::friend.age}} years old.
31631+ </li>
31632+ </ul>
31633+ <code>track by $index</code>, with age one-time binding:
31634+ <ul class="example-animate-container">
31635+ <li class="animate-repeat" ng-repeat="friend in friends track by $index">
31636+ {{friend.name}} is {{::friend.age}} years old.
31637+ </li>
31638+ </ul>
31639+ </div>
31640+ </file>
31641+ <file name="animations.css">
31642+ .example-animate-container {
31643+ background:white;
31644+ border:1px solid black;
31645+ list-style:none;
31646+ margin:0;
31647+ padding:0 10px;
31648+ }
31649+
31650+ .animate-repeat {
31651+ line-height:30px;
31652+ list-style:none;
31653+ box-sizing:border-box;
31654+ }
31655+
31656+ .animate-repeat.ng-move,
31657+ .animate-repeat.ng-enter,
31658+ .animate-repeat.ng-leave {
31659+ transition:all linear 0.5s;
31660+ }
31661+
31662+ .animate-repeat.ng-leave.ng-leave-active,
31663+ .animate-repeat.ng-move,
31664+ .animate-repeat.ng-enter {
31665+ opacity:0;
31666+ max-height:0;
31667+ }
31668+
31669+ .animate-repeat.ng-leave,
31670+ .animate-repeat.ng-move.ng-move-active,
31671+ .animate-repeat.ng-enter.ng-enter-active {
31672+ opacity:1;
31673+ max-height:30px;
31674+ }
31675+ </file>
31676+ </example>
31677+
3159231678 *
3159331679 * ## Special repeat start and end points
3159431680 * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending
@@ -31665,24 +31751,38 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
3166531751 * more than one tracking expression value resolve to the same key. (This would mean that two distinct objects are
3166631752 * mapped to the same DOM element, which is not possible.)
3166731753 *
31668- * <div class="alert alert-warning">
31669- * <strong>Note:</strong> the `track by` expression must come last - after any filters, and the alias expression.
31670- * </div>
31754+ * *Default tracking: $id()*: `item in items` is equivalent to `item in items track by $id(item)`.
31755+ * This implies that the DOM elements will be associated by item identity in the collection.
3167131756 *
31672- * For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements
31673- * will be associated by item identity in the array.
31757+ * The built-in `$id()` function can be used to assign a unique
31758+ * `$$hashKey` property to each item in the collection. This property is then used as a key to associated DOM elements
31759+ * with the corresponding item in the collection by identity. Moving the same object would move
31760+ * the DOM element in the same way in the DOM.
31761+ * Note that the default id function does not support duplicate primitive values (`number`, `string`),
31762+ * but supports duplictae non-primitive values (`object`) that are *equal* in shape.
3167431763 *
31675- * For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique
31676- * `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements
31677- * with the corresponding item in the array by identity. Moving the same object in array would move the DOM
31678- * element in the same way in the DOM.
31764+ * *Custom Expression*: It is possible to use any AngularJS expression to compute the tracking
31765+ * id, for example with a function, or using a property on the collection items.
31766+ * `item in items track by item.id` is a typical pattern when the items have a unique identifier,
31767+ * e.g. database id. In this case the object identity does not matter. Two objects are considered
31768+ * equivalent as long as their `id` property is same.
31769+ * Tracking by unique identifier is the most performant way and should be used whenever possible.
3167931770 *
31680- * For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this
31681- * case the object identity does not matter. Two objects are considered equivalent as long as their `id`
31682- * property is same.
31771+ * *$index*: This special property tracks the collection items by their index, and
31772+ * re-uses the DOM elements that match that index, e.g. `item in items track by $index`. This can
31773+ * be used for a performance improvement if no unique identfier is available and the identity of
31774+ * the collection items cannot be easily computed. It also allows duplicates.
3168331775 *
31684- * For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter
31685- * to items in conjunction with a tracking expression.
31776+ * <div class="alert alert-warning">
31777+ * <strong>Note:</strong> Re-using DOM elements can have unforeseen effects. Read the
31778+ * {@link ngRepeat#tracking-and-duplicates section on tracking and duplicates} for
31779+ * more info.
31780+ * </div>
31781+ *
31782+ * <div class="alert alert-warning">
31783+ * <strong>Note:</strong> the `track by` expression must come last - after any filters, and the alias expression:
31784+ * `item in items | filter:searchText as results track by item.id`
31785+ * </div>
3168631786 *
3168731787 * * `variable in expression as alias_expression` – You can also provide an optional alias expression which will then store the
3168831788 * intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message
@@ -31691,10 +31791,10 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
3169131791 * For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after
3169231792 * the items have been processed through the filter.
3169331793 *
31694- * Please note that `as [variable name] is not an operator but rather a part of ngRepeat micro-syntax so it can be used only at the end
31695- * (and not as operator, inside an expression).
31794+ * Please note that `as [variable name] is not an operator but rather a part of ngRepeat
31795+ * micro-syntax so it can be used only after all filters (and not as operator, inside an expression).
3169631796 *
31697- * For example: `item in items | filter : x | orderBy : order | limitTo : limit as results` .
31797+ * For example: `item in items | filter : x | orderBy : order | limitTo : limit as results track by item.id ` .
3169831798 *
3169931799 * @example
3170031800 * This example uses `ngRepeat` to display a list of people. A filter is used to restrict the displayed
@@ -31705,7 +31805,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
3170531805 I have {{friends.length}} friends. They are:
3170631806 <input type="search" ng-model="q" placeholder="filter friends..." aria-label="filter friends" />
3170731807 <ul class="example-animate-container">
31708- <li class="animate-repeat" ng-repeat="friend in friends | filter:q as results">
31808+ <li class="animate-repeat" ng-repeat="friend in friends | filter:q as results track by friend.name ">
3170931809 [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
3171031810 </li>
3171131811 <li class="animate-repeat" ng-if="results.length === 0">
@@ -32862,7 +32962,6 @@ var ngTranscludeMinErr = minErr('ngTransclude');
3286232962var ngTranscludeDirective = ['$compile', function($compile) {
3286332963 return {
3286432964 restrict: 'EAC',
32865- terminal: true,
3286632965 compile: function ngTranscludeCompile(tElement) {
3286732966
3286832967 // Remove and cache any original content to act as a fallback
0 commit comments