Why does AngularJS include an empty option in select?

The empty option is generated when a value referenced by ng-model doesn't exist in a set of options passed to ng-options. This happens to prevent accidental model selection: AngularJS can see that the initial model is either undefined or not in the set of options and don't want to decide model value on its own.

If you want to get rid of the empty option just select an initial value in your controller, something like:

$scope.form.type = $scope.typeOptions[0].value;

Here is the jsFiddle: http://jsfiddle.net/MTfRD/3/

In short: the empty option means that no valid model is selected (by valid I mean: from the set of options). You need to select a valid model value to get rid of this empty option.


If you want an initial value, see @pkozlowski.opensource's answer, which FYI can also be implemented in the view (rather than in the controller) using ng-init:

<select ng-model="form.type" required="required" ng-init="form.type='bug'"
  ng-options="option.value as option.name for option in typeOptions" >
</select>

If you don't want an initial value, "a single hard-coded element, with the value set to an empty string, can be nested into the element. This element will then represent null or "not selected" option":

<select ng-model="form.type" required="required"
  ng-options="option.value as option.name for option in typeOptions" >
    <option style="display:none" value="">select a type</option>
</select>

Angular < 1.4

For anyone out there that treat "null" as valid value for one of the options (so imagine that "null" is a value of one of the items in typeOptions in example below), I found that simplest way to make sure that automatically added option is hidden is to use ng-if.

<select ng-options="option.value as option.name for option in typeOptions">
    <option value="" ng-if="false"></option>
</select>

Why ng-if and not ng-hide? Because you want css selectors that would target first option inside above select to target "real" option, not the one that's hidden. It gets useful when you're using protractor for e2e testing and (for whatever reason) you use by.css() to target select options.

Angular >= 1.4

Due to the refactoring of the select and options directives, using ng-if is no longer a viable option so you gotta turn to ng-show="false" to make it work again.


Maybe useful for someone:

If you want to use plain options instead of ng-options, you could do like below:

<select ng-model="sortorder" ng-init="sortorder='publish_date'">
  <option value="publish_date">Ascending</option>
  <option value="-publish_date">Descending</option>
</select>

Set the model inline. Use ng-init to get rid of empty option