Unified
Split
Showing
with
45 additions
and 21 deletions.
- +45 −21 src/ng/directive/select.js
| @@ -13,14 +13,15 @@ var ngOptionsMinErr = minErr('ngOptions'); | ||
| * | ||
| * The `ngOptions` attribute can be used to dynamically generate a list of `<option>` | ||
| * elements for the `<select>` element using the array or object obtained by evaluating the | ||
| * `ngOptions` comprehension_expression. | ||
| * `ngOptions` comprehension expression. | ||
| * | ||
| * In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a | ||
| * similar result. However, the `ngOptions` provides some benefits such as reducing memory and | ||
| * similar result. However, `ngOptions` provides some benefits such as reducing memory and | ||
| * increasing speed by not creating a new scope for each repeated instance, as well as providing | ||
| * more flexibility in how the `select`'s model is assigned via `select as`. `ngOptions` should be | ||
| * used when the `select` model needs to be bound to a non-string value. This is because an option | ||
| * element can only be bound to string values at present. | ||
| * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the | ||
| * comprehension expression. `ngOptions` should be used when the `<select>` model needs to be bound | ||
| * to a non-string value. This is because an option element can only be bound to string values at | ||
| * present. | ||
| * | ||
| * When an item in the `<select>` menu is selected, the array element or object property | ||
| * represented by the selected option will be bound to the model identified by the `ngModel` | ||
| @@ -35,28 +36,51 @@ var ngOptionsMinErr = minErr('ngOptions'); | ||
| * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/). | ||
| * </div> | ||
| * | ||
| * ## `select as` | ||
| * ## `select` **`as`** | ||
| * | ||
| * Using `select as` will bind the result of the `select as` expression to the model, but | ||
| * Using `select` **`as`** will bind the result of the `select` expression to the model, but | ||
| * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources) | ||
| * or property name (for object data sources) of the value within the collection. If a `track by` expression | ||
| * or property name (for object data sources) of the value within the collection. If a **`track by`** expression | ||
| * is used, the result of that expression will be set as the value of the `option` and `select` elements. | ||
| * | ||
| * ### `select as` with `track by` | ||
| * | ||
| * Using `select as` together with `track by` is not recommended. Reasoning: | ||
| * ### `select` **`as`** and **`track by`** | ||
| * | ||
| * <div class="alert alert-warning"> | ||
| * Do not use `select` **`as`** and **`track by`** in the same expression. They are not designed to work together. | ||
| * </div> | ||
| * | ||
| * Consider the following example: | ||
| * | ||
| * ```html | ||
| * <select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected"> | ||
| * ``` | ||
| * | ||
| * ```js | ||
| * $scope.values = [{ | ||
| * id: 1, | ||
| * label: 'aLabel', | ||
| * subItem: { name: 'aSubItem' } | ||
| * }, { | ||
| * id: 2, | ||
| * label: 'bLabel', | ||
| * subItem: { name: 'bSubItem' } | ||
| * }]; | ||
| * | ||
| * $scope.selected = { name: 'aSubItem' }; | ||
| * ``` | ||
| * | ||
| * With the purpose of preserving the selection, the **`track by`** expression is always applied to the element | ||
| * of the data source (to `item` in this example). To calculate whether an element is selected, we do the | ||
| * following: | ||
| * | ||
| * 1. Apply **`track by`** to the elements in the array. In the example: `[1, 2]` | ||
| * 2. Apply **`track by`** to the already selected value in `ngModel`. | ||
| * In the example: this is not possible as **`track by`** refers to `item.id`, but the selected | ||
| * value from `ngModel` is `{name: 'aSubItem'}`, so the **`track by`** expression is applied to | ||
| * a wrong object, the selected element can't be found, `<select>` is always reset to the "not | ||
| * selected" option. | ||
| * | ||
| * - Example: <select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected"> | ||
| * values: [{id: 1, label: 'aLabel', subItem: {name: 'aSubItem'}}, {id: 2, label: 'bLabel', subItem: {name: 'bSubItem'}}], | ||
| * $scope.selected = {name: 'aSubItem'}; | ||
| * - track by is always applied to `value`, with the purpose of preserving the selection, | ||
| * (to `item` in this case) | ||
| * - to calculate whether an item is selected we do the following: | ||
| * 1. apply `track by` to the values in the array, e.g. | ||
| * In the example: [1,2] | ||
| * 2. apply `track by` to the already selected value in `ngModel`: | ||
| * In the example: this is not possible, as `track by` refers to `item.id`, but the selected | ||
| * value from `ngModel` is `{name: aSubItem}`. | ||
| * | ||
| * @param {string} ngModel Assignable angular expression to data-bind to. | ||
| * @param {string=} name Property name of the form under which the control is published. | ||