function selectPreLink(scope, element, attr, ctrls) {

      // if ngModel is not defined, we don't need to do anything
      var ngModelCtrl = ctrls[1];
      if (!ngModelCtrl) return;

      var selectCtrl = ctrls[0];

      selectCtrl.ngModelCtrl = ngModelCtrl;

      // When the selected item(s) changes we delegate getting the value of the select control
      // to the `readValue` method, which can be changed if the select can have multiple
      // selected values or if the options are being generated by `ngOptions`
      element.on('change', function() {
        scope.$apply(function() {
          ngModelCtrl.$setViewValue(selectCtrl.readValue());
        });
      });

      // If the select allows multiple values then we need to modify how we read and write
      // values from and to the control; also what it means for the value to be empty and
      // we have to add an extra watch since ngModel doesn't work well with arrays - it
      // doesn't trigger rendering if only an item in the array changes.
      if (attr.multiple) {

        // Read value now needs to check each option to see if it is selected
        selectCtrl.readValue = function readMultipleValue() {
          var array = [];
          forEach(element.find('option'), function(option) {
            if (option.selected) {
              array.push(option.value);
            }
          });
          return array;
        };

        // Write value now needs to set the selected property of each matching option
        selectCtrl.writeValue = function writeMultipleValue(value) {
          var items = new HashMap(value);
          forEach(element.find('option'), function(option) {
            option.selected = isDefined(items.get(option.value));
          });
        };

        // we have to do it on each watch since ngModel watches reference, but
        // we need to work of an array, so we need to see if anything was inserted/removed
        var lastView, lastViewRef = NaN;
        scope.$watch(function selectMultipleWatch() {
          if (lastViewRef === ngModelCtrl.$viewValue && !equals(lastView, ngModelCtrl.$viewValue)) {
            lastView = shallowCopy(ngModelCtrl.$viewValue);
            ngModelCtrl.$render();
          }
          lastViewRef = ngModelCtrl.$viewValue;
        });

        // If we are a multiple select then value is now a collection
        // so the meaning of $isEmpty changes
        ngModelCtrl.$isEmpty = function(value) {
          return !value || value.length === 0;
        };

      }
    }
@ngdoc directive
@name select
@restrict E

@description
HTML `SELECT` element with angular data-binding.

The `select` directive is used together with {@link ngModel `ngModel`} to provide data-binding
between the scope and the `<select>` control (including setting default values).
It also handles dynamic `<option>` elements, which can be added using the {@link ngRepeat `ngRepeat}` or
{@link ngOptions `ngOptions`} directives.

When an item in the `<select>` menu is selected, the value of the selected option will be bound
to the model identified by the `ngModel` directive. With static or repeated options, this is
the content of the `value` attribute or the textContent of the `<option>`, if the value attribute is missing.
If you want dynamic value attributes, you can use interpolation inside the value attribute.

<div class="alert alert-warning">
Note that the value of a `select` directive used without `ngOptions` is always a string.
When the model needs to be bound to a non-string value, you must either explictly convert it
using a directive (see example below) or use `ngOptions` to specify the set of options.
This is because an option element can only be bound to string values at present.
</div>

If the viewValue of `ngModel` does not match any of the options, then the control
will automatically add an "unknown" option, which it then removes when the mismatch is resolved.

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.

<div class="alert alert-info">
In many cases, `ngRepeat` can be used on `<option>` elements instead of {@link ng.directive:ngOptions
ngOptions} to achieve a similar result. However, `ngOptions` provides some benefits, such as
more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
comprehension expression, and additionally in reducing memory and increasing speed by not creating
a new scope for each repeated instance.
</div>


@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=} multiple Allows multiple options to be selected. The selected values will be
    bound to the model as an array.
@param {string=} required Sets `required` validation error key if the value is not 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 {string=} ngChange Angular expression to be executed when selected option(s) changes due to user
   interaction with the select element.
@param {string=} ngOptions sets the options that the select is populated with and defines what is
set on the model on selection. See {@link ngOptions `ngOptions`}.

@example
### Simple `select` elements with static options

<example name="static-select" module="staticSelect">
<file name="index.html">
<div ng-controller="ExampleController">
  <form name="myForm">
    <label for="singleSelect"> Single select: </label><br>
    <select name="singleSelect" ng-model="data.singleSelect">
      <option value="option-1">Option 1</option>
      <option value="option-2">Option 2</option>
    </select><br>

    <label for="singleSelect"> Single select with "not selected" option and dynamic option values: </label><br>
    <select name="singleSelect" id="singleSelect" ng-model="data.singleSelect">
      <option value="">---Please select---</option> <!-- not selected / blank option -->
      <option value="{{data.option1}}">Option 1</option> <!-- interpolation -->
      <option value="option-2">Option 2</option>
    </select><br>
    <button ng-click="forceUnknownOption()">Force unknown option</button><br>
    <tt>singleSelect = {{data.singleSelect}}</tt>

    <hr>
    <label for="multipleSelect"> Multiple select: </label><br>
    <select name="multipleSelect" id="multipleSelect" ng-model="data.multipleSelect" multiple>
      <option value="option-1">Option 1</option>
      <option value="option-2">Option 2</option>
      <option value="option-3">Option 3</option>
    </select><br>
    <tt>multipleSelect = {{data.multipleSelect}}</tt><br/>
  </form>
</div>
</file>
<file name="app.js">
 angular.module('staticSelect', [])
   .controller('ExampleController', ['$scope', function($scope) {
     $scope.data = {
      singleSelect: null,
      multipleSelect: [],
      option1: 'option-1',
     };

     $scope.forceUnknownOption = function() {
       $scope.data.singleSelect = 'nonsense';
     };
  }]);
</file>
</example>

### Using `ngRepeat` to generate `select` options
<example name="ngrepeat-select" module="ngrepeatSelect">
<file name="index.html">
<div ng-controller="ExampleController">
  <form name="myForm">
    <label for="repeatSelect"> Repeat select: </label>
    <select name="repeatSelect" id="repeatSelect" ng-model="data.repeatSelect">
      <option ng-repeat="option in data.availableOptions" value="{{option.id}}">{{option.name}}</option>
    </select>
  </form>
  <hr>
  <tt>repeatSelect = {{data.repeatSelect}}</tt><br/>
</div>
</file>
<file name="app.js">
 angular.module('ngrepeatSelect', [])
   .controller('ExampleController', ['$scope', function($scope) {
     $scope.data = {
      repeatSelect: null,
      availableOptions: [
        {id: '1', name: 'Option A'},
        {id: '2', name: 'Option B'},
        {id: '3', name: 'Option C'}
      ],
     };
  }]);
</file>
</example>


### Using `select` with `ngOptions` and setting a default value
See the {@link ngOptions ngOptions documentation} for more `ngOptions` usage examples.

<example name="select-with-default-values" module="defaultValueSelect">
<file name="index.html">
<div ng-controller="ExampleController">
  <form name="myForm">
    <label for="mySelect">Make a choice:</label>
    <select name="mySelect" id="mySelect"
      ng-options="option.name for option in data.availableOptions track by option.id"
      ng-model="data.selectedOption"></select>
  </form>
  <hr>
  <tt>option = {{data.selectedOption}}</tt><br/>
</div>
</file>
<file name="app.js">
 angular.module('defaultValueSelect', [])
   .controller('ExampleController', ['$scope', function($scope) {
     $scope.data = {
      availableOptions: [
        {id: '1', name: 'Option A'},
        {id: '2', name: 'Option B'},
        {id: '3', name: 'Option C'}
      ],
      selectedOption: {id: '3', name: 'Option C'} //This sets the default value of the select in the ui
      };
  }]);
</file>
</example>


### Binding `select` to a non-string value via `ngModel` parsing / formatting

<example name="select-with-non-string-options" module="nonStringSelect">
  <file name="index.html">
    <select ng-model="model.id" convert-to-number>
      <option value="0">Zero</option>
      <option value="1">One</option>
      <option value="2">Two</option>
    </select>
    {{ model }}
  </file>
  <file name="app.js">
    angular.module('nonStringSelect', [])
      .run(function($rootScope) {
        $rootScope.model = { id: 2 };
      })
      .directive('convertToNumber', function() {
        return {
          require: 'ngModel',
          link: function(scope, element, attrs, ngModel) {
            ngModel.$parsers.push(function(val) {
              return parseInt(val, 10);
            });
            ngModel.$formatters.push(function(val) {
              return '' + val;
            });
          }
        };
      });
  </file>
  <file name="protractor.js" type="protractor">
    it('should initialize to model', function() {
      var select = element(by.css('select'));
      expect(element(by.model('model.id')).$('option:checked').getText()).toEqual('Two');
    });
  </file>
</example>