1
1
/**
2
- * @license AngularJS v1.6.9-build.5530 +sha.07d84dd
2
+ * @license AngularJS v1.6.9-build.5546 +sha.ab386cd
3
3
* (c) 2010-2018 Google, Inc. http://angularjs.org
4
4
* License: MIT
5
5
*/
@@ -106,7 +106,7 @@ function minErr(module, ErrorConstructor) {
106
106
return match;
107
107
});
108
108
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 /' +
110
110
(module ? module + '/' : '') + code;
111
111
112
112
for (i = 0, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
@@ -2534,7 +2534,13 @@ function setupModuleLoader(window) {
2534
2534
* @param {Function} configFn Execute this function on module load. Useful for service
2535
2535
* configuration.
2536
2536
* @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
+ *
2538
2544
* For more about how to configure services, see
2539
2545
* {@link providers#provider-recipe Provider Recipe}.
2540
2546
*/
@@ -2774,7 +2780,7 @@ function toDebugString(obj, maxDepth) {
2774
2780
var version = {
2775
2781
// These placeholder strings will be replaced by grunt's `build` task.
2776
2782
// 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 ',
2778
2784
major: 1,
2779
2785
minor: 6,
2780
2786
dot: 9,
@@ -2924,7 +2930,7 @@ function publishExternalAPI(angular) {
2924
2930
});
2925
2931
}
2926
2932
])
2927
- .info({ angularVersion: '1.6.9-build.5530 +sha.07d84dd ' });
2933
+ .info({ angularVersion: '1.6.9-build.5546 +sha.ab386cd ' });
2928
2934
}
2929
2935
2930
2936
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@@ -4578,6 +4584,9 @@ function annotate(fn, strictDi, name) {
4578
4584
* which lets you specify whether the {@link ng.$log $log} service will log debug messages to the
4579
4585
* console or not.
4580
4586
*
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
+ *
4581
4590
* @param {string} name The name of the instance. NOTE: the provider will be available under `name +
4582
4591
'Provider'` key.
4583
4592
* @param {(Object|function())} provider If the provider is:
@@ -31524,71 +31533,148 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
31524
31533
* For example, if an item is added to the collection, `ngRepeat` will know that all other items
31525
31534
* already have DOM elements, and will not re-render them.
31526
31535
*
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}.
31549
31539
*
31550
31540
* <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 .
31557
31547
* </div>
31558
31548
*
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
31564
31550
*
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:
31573
31554
*
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.
31581
31558
*
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.
31591
31561
*
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
+
31592
31678
*
31593
31679
* ## Special repeat start and end points
31594
31680
* 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,
31665
31751
* more than one tracking expression value resolve to the same key. (This would mean that two distinct objects are
31666
31752
* mapped to the same DOM element, which is not possible.)
31667
31753
*
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.
31671
31756
*
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.
31674
31763
*
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.
31679
31770
*
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.
31683
31775
*
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>
31686
31786
*
31687
31787
* * `variable in expression as alias_expression` – You can also provide an optional alias expression which will then store the
31688
31788
* 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,
31691
31791
* For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after
31692
31792
* the items have been processed through the filter.
31693
31793
*
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).
31696
31796
*
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 ` .
31698
31798
*
31699
31799
* @example
31700
31800
* 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,
31705
31805
I have {{friends.length}} friends. They are:
31706
31806
<input type="search" ng-model="q" placeholder="filter friends..." aria-label="filter friends" />
31707
31807
<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 ">
31709
31809
[{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
31710
31810
</li>
31711
31811
<li class="animate-repeat" ng-if="results.length === 0">
@@ -32862,7 +32962,6 @@ var ngTranscludeMinErr = minErr('ngTransclude');
32862
32962
var ngTranscludeDirective = ['$compile', function($compile) {
32863
32963
return {
32864
32964
restrict: 'EAC',
32865
- terminal: true,
32866
32965
compile: function ngTranscludeCompile(tElement) {
32867
32966
32868
32967
// Remove and cache any original content to act as a fallback
0 commit comments