@@ -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 AngularJS expression to data-bind to.
115121 * @param {comprehension_expression } ngOptions in one of the following forms:
@@ -285,7 +291,7 @@ var ngOptionsDirective = ['$compile', '$document', '$parse', function($compile,
285291 function ( value , locals ) { return trackByFn ( scope , locals ) ; } :
286292 function getHashOfValue ( value ) { return hashKey ( value ) ; } ;
287293 var getTrackByValue = function ( value , key ) {
288- return getTrackByValueFn ( value , getLocals ( value , key ) ) ;
294+ return getTrackByValueFn ( value , getLocals ( value , key , true ) ) ;
289295 } ;
290296
291297 var displayFn = $parse ( match [ 2 ] || match [ 1 ] ) ;
@@ -294,12 +300,10 @@ var ngOptionsDirective = ['$compile', '$document', '$parse', function($compile,
294300 var valuesFn = $parse ( match [ 8 ] ) ;
295301
296302 var locals = { } ;
297- var getLocals = keyName ? function ( value , key ) {
298- locals [ keyName ] = key ;
299- locals [ valueName ] = value ;
300- return locals ;
301- } : function ( value ) {
303+ var getLocals = function ( value , key , isViewValue ) {
304+ if ( keyName ) locals [ keyName ] = key ;
302305 locals [ valueName ] = value ;
306+ locals [ '$value' ] = isViewValue ? value : viewValueFn ( value , locals ) ;
303307 return locals ;
304308 } ;
305309
@@ -345,7 +349,7 @@ var ngOptionsDirective = ['$compile', '$document', '$parse', function($compile,
345349 var key = ( optionValues === optionValuesKeys ) ? index : optionValuesKeys [ index ] ;
346350 var value = optionValues [ key ] ;
347351
348- var locals = getLocals ( value , key ) ;
352+ var locals = getLocals ( value , key , true ) ;
349353 var selectValue = getTrackByValueFn ( value , locals ) ;
350354 watchedArray . push ( selectValue ) ;
351355
@@ -378,7 +382,7 @@ var ngOptionsDirective = ['$compile', '$document', '$parse', function($compile,
378382 for ( var index = 0 ; index < optionValuesLength ; index ++ ) {
379383 var key = ( optionValues === optionValuesKeys ) ? index : optionValuesKeys [ index ] ;
380384 var value = optionValues [ key ] ;
381- var locals = getLocals ( value , key ) ;
385+ var locals = getLocals ( value , key , false ) ;
382386 var viewValue = viewValueFn ( scope , locals ) ;
383387 var selectValue = getTrackByValueFn ( viewValue , locals ) ;
384388 var label = displayFn ( scope , locals ) ;
0 commit comments