@@ -66,9 +66,7 @@ var ngOptionsMinErr = minErr('ngOptions');
6666 *
6767 * ### `select` **`as`** and **`track by`**
6868 *
69- * <div class="alert alert-warning">
70- * Be careful when using `select` **`as`** and **`track by`** in the same expression.
71- * </div>
69+ * When using `select` **`as`** and **`track by`** in the same expression use the `$value` variable.
7270 *
7371 * Given this array of items on the $scope:
7472 *
@@ -110,6 +108,14 @@ var ngOptionsMinErr = minErr('ngOptions');
110108 * expression evaluates to `items[0].subItem.id` (which is undefined). As a result, the model value
111109 * is not matched against any `<option>` and the `<select>` appears as having no selected value.
112110 *
111+ * here is the fixed version of the broken example above.
112+ *
113+ * ```html
114+ * <select ng-options="item.subItem as item.label for item in items track by $value.id" ng-model="selected"></select>
115+ * ```
116+ * ```js
117+ * $scope.selected = $scope.items[0].subItem;
118+ * ```
113119 *
114120 * @param {string } ngModel Assignable angular expression to data-bind to.
115121 * @param {string= } name Property name of the form under which the control is published.
@@ -283,7 +289,7 @@ var ngOptionsDirective = ['$compile', '$document', '$parse', function($compile,
283289 function ( value , locals ) { return trackByFn ( scope , locals ) ; } :
284290 function getHashOfValue ( value ) { return hashKey ( value ) ; } ;
285291 var getTrackByValue = function ( value , key ) {
286- return getTrackByValueFn ( value , getLocals ( value , key ) ) ;
292+ return getTrackByValueFn ( value , getLocals ( value , key , true ) ) ;
287293 } ;
288294
289295 var displayFn = $parse ( match [ 2 ] || match [ 1 ] ) ;
@@ -292,12 +298,10 @@ var ngOptionsDirective = ['$compile', '$document', '$parse', function($compile,
292298 var valuesFn = $parse ( match [ 8 ] ) ;
293299
294300 var locals = { } ;
295- var getLocals = keyName ? function ( value , key ) {
296- locals [ keyName ] = key ;
297- locals [ valueName ] = value ;
298- return locals ;
299- } : function ( value ) {
301+ var getLocals = function ( value , key , isViewValue ) {
302+ if ( keyName ) locals [ keyName ] = key ;
300303 locals [ valueName ] = value ;
304+ locals [ '$value' ] = isViewValue ? value : viewValueFn ( value , locals ) ;
301305 return locals ;
302306 } ;
303307
@@ -343,7 +347,7 @@ var ngOptionsDirective = ['$compile', '$document', '$parse', function($compile,
343347 var key = ( optionValues === optionValuesKeys ) ? index : optionValuesKeys [ index ] ;
344348 var value = optionValues [ key ] ;
345349
346- var locals = getLocals ( value , key ) ;
350+ var locals = getLocals ( value , key , true ) ;
347351 var selectValue = getTrackByValueFn ( value , locals ) ;
348352 watchedArray . push ( selectValue ) ;
349353
@@ -376,7 +380,7 @@ var ngOptionsDirective = ['$compile', '$document', '$parse', function($compile,
376380 for ( var index = 0 ; index < optionValuesLength ; index ++ ) {
377381 var key = ( optionValues === optionValuesKeys ) ? index : optionValuesKeys [ index ] ;
378382 var value = optionValues [ key ] ;
379- var locals = getLocals ( value , key ) ;
383+ var locals = getLocals ( value , key , false ) ;
380384 var viewValue = viewValueFn ( scope , locals ) ;
381385 var selectValue = getTrackByValueFn ( viewValue , locals ) ;
382386 var label = displayFn ( scope , locals ) ;
0 commit comments