function Option(selectValue, viewValue, label, group, disabled) {
      this.selectValue = selectValue;
      this.viewValue = viewValue;
      this.label = label;
      this.group = group;
      this.disabled = disabled;
    }
@ngdoc directive
@name ngOptions
@restrict A

@description

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.

In many cases, {@link ng.directive:ngRepeat ngRepeat} can be used on `<option>` elements instead of
`ngOptions` to achieve a similar result. However, `ngOptions` provides some benefits:
- more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
comprehension expression
- reduced memory consumption by not creating a new scope for each repeated instance
- increased render speed by creating the options in a documentFragment instead of individually

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`
directive.

Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
be nested into the `<select>` element. This element will then represent the `null` or "not selected"
option. See example below for demonstration.

## Complex Models (objects or collections)

By default, `ngModel` watches the model by reference, not value. This is important to know when
binding the select to a model that is an object or a collection.

One issue occurs if you want to preselect an option. For example, if you set
the model to an object that is equal to an object in your collection, `ngOptions` won't be able to set the selection,
because the objects are not identical. So by default, you should always reference the item in your collection
for preselections, e.g.: `$scope.selected = $scope.collection[3]`.

Another solution is to use a `track by` clause, because then `ngOptions` will track the identity
of the item not by reference, but by the result of the `track by` expression. For example, if your
collection items have an id property, you would `track by item.id`.

A different issue with objects or collections is that ngModel won't detect if an object property or
a collection item changes. For that reason, `ngOptions` additionally watches the model using
`$watchCollection`, when the expression contains a `track by` clause or the the select has the `multiple` attribute.
This allows ngOptions to trigger a re-rendering of the options even if the actual object/collection
has not changed identity, but only a property on the object or an item in the collection changes.

Note that `$watchCollection` does a shallow comparison of the properties of the object (or the items in the collection
if the model is an array). This means that changing a property deeper than the first level inside the
object/collection will not trigger a re-rendering.

## `select` **`as`**

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
is used, the result of that expression will be set as the value of the `option` and `select` elements.


### `select` **`as`** and **`track by`**

<div class="alert alert-warning">
Be careful when using `select` **`as`** and **`track by`** in the same expression.
</div>

Given this array of items on the $scope:

```js
$scope.items = [{
  id: 1,
  label: 'aLabel',
  subItem: { name: 'aSubItem' }
}, {
  id: 2,
  label: 'bLabel',
  subItem: { name: 'bSubItem' }
}];
```

This will work:

```html
<select ng-options="item as item.label for item in items track by item.id" ng-model="selected"></select>
```
```js
$scope.selected = $scope.items[0];
```

but this will not work:

```html
<select ng-options="item.subItem as item.label for item in items track by item.id" ng-model="selected"></select>
```
```js
$scope.selected = $scope.items[0].subItem;
```

In both examples, the **`track by`** expression is applied successfully to each `item` in the
`items` array. Because the selected option has been set programmatically in the controller, the
**`track by`** expression is also applied to the `ngModel` value. In the first example, the
`ngModel` value is `items[0]` and the **`track by`** expression evaluates to `items[0].id` with
no issue. In the second example, the `ngModel` value is `items[0].subItem` and the **`track by`**
expression evaluates to `items[0].subItem.id` (which is undefined). As a result, the model value
is not matched against any `<option>` and the `<select>` appears as having no selected value.


@param {string} ngModel Assignable angular expression to data-bind to.
@param {string=} name Property name of the form under which the control is published.
@param {string=} required The control is considered valid only if value is entered.
@param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
   the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
   `required` when you want to data-bind to the `required` attribute.
@param {comprehension_expression=} ngOptions in one of the following forms:

  * for array data sources:
    * `label` **`for`** `value` **`in`** `array`
    * `select` **`as`** `label` **`for`** `value` **`in`** `array`
    * `label` **`group by`** `group` **`for`** `value` **`in`** `array`
    * `label` **`disable when`** `disable` **`for`** `value` **`in`** `array`
    * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
    * `label` **`disable when`** `disable` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
    * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr`
       (for including a filter with `track by`)
  * for object data sources:
    * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
    * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
    * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`
    * `label` **`disable when`** `disable` **`for (`**`key`**`,`** `value`**`) in`** `object`
    * `select` **`as`** `label` **`group by`** `group`
        **`for` `(`**`key`**`,`** `value`**`) in`** `object`
    * `select` **`as`** `label` **`disable when`** `disable`
        **`for` `(`**`key`**`,`** `value`**`) in`** `object`

Where:

  * `array` / `object`: an expression which evaluates to an array / object to iterate over.
  * `value`: local variable which will refer to each item in the `array` or each property value
     of `object` during iteration.
  * `key`: local variable which will refer to a property name in `object` during iteration.
  * `label`: The result of this expression will be the label for `<option>` element. The
    `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).
  * `select`: The result of this expression will be bound to the model of the parent `<select>`
     element. If not specified, `select` expression will default to `value`.
  * `group`: The result of this expression will be used to group options using the `<optgroup>`
     DOM element.
  * `disable`: The result of this expression will be used to disable the rendered `<option>`
     element. Return `true` to disable.
  * `trackexpr`: Used when working with an array of objects. The result of this expression will be
     used to identify the objects in the array. The `trackexpr` will most likely refer to the
    `value` variable (e.g. `value.propertyName`). With this the selection is preserved
     even when the options are recreated (e.g. reloaded from the server).

@example
    <example module="selectExample" name="select">
      <file name="index.html">
        <script>
        angular.module('selectExample', [])
          .controller('ExampleController', ['$scope', function($scope) {
            $scope.colors = [
              {name:'black', shade:'dark'},
              {name:'white', shade:'light', notAnOption: true},
              {name:'red', shade:'dark'},
              {name:'blue', shade:'dark', notAnOption: true},
              {name:'yellow', shade:'light', notAnOption: false}
            ];
            $scope.myColor = $scope.colors[2]; // red
          }]);
        </script>
        <div ng-controller="ExampleController">
          <ul>
            <li ng-repeat="color in colors">
              <label>Name: <input ng-model="color.name"></label>
              <label><input type="checkbox" ng-model="color.notAnOption"> Disabled?</label>
              <button ng-click="colors.splice($index, 1)" aria-label="Remove">X</button>
            </li>
            <li>
              <button ng-click="colors.push({})">add</button>
            </li>
          </ul>
          <hr/>
          <label>Color (null not allowed):
            <select ng-model="myColor" ng-options="color.name for color in colors"></select>
          </label><br/>
          <label>Color (null allowed):
          <span  class="nullable">
            <select ng-model="myColor" ng-options="color.name for color in colors">
              <option value="">-- choose color --</option>
            </select>
          </span></label><br/>

          <label>Color grouped by shade:
            <select ng-model="myColor" ng-options="color.name group by color.shade for color in colors">
            </select>
          </label><br/>

          <label>Color grouped by shade, with some disabled:
            <select ng-model="myColor"
                  ng-options="color.name group by color.shade disable when color.notAnOption for color in colors">
            </select>
          </label><br/>



          Select <button ng-click="myColor = { name:'not in list', shade: 'other' }">bogus</button>.
          <br/>
          <hr/>
          Currently selected: {{ {selected_color:myColor} }}
          <div style="border:solid 1px black; height:20px"
               ng-style="{'background-color':myColor.name}">
          </div>
        </div>
      </file>
      <file name="protractor.js" type="protractor">
         it('should check ng-options', function() {
           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');
           element.all(by.model('myColor')).first().click();
           element.all(by.css('select[ng-model="myColor"] option')).first().click();
           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');
           element(by.css('.nullable select[ng-model="myColor"]')).click();
           element.all(by.css('.nullable select[ng-model="myColor"] option')).first().click();
           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null');
         });
      </file>
    </example>