The
ngRepeat
directive can be used to create the options of a select element, however, there is a much more recommended directive that should be used for this purpose the ngOptions directive.
Through an expression, we need to indicate the property of the scope from which the directive will iterate, the name of the temporary variable that will hold the content of each loop's iteration, and the property of the variable that should be displayed.
One thing to note is that
ngModel
directive is required for
ngOptions
to work.
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
Example
In the following example, we have introduced a list of colors.
index.html
snippet
<!doctype html>
<html ng-app="parking">
<head>
<title>Parking</title>
<script src="angular.js"></script>
<script>
var parking = angular.module("parking", []);
parking.controller("parkingCtrl", function($scope) {
$scope.appTitle = "Parking";
$scope.cars = [];
$scope.colors = ["White", "Black", "Blue", "Red",
"Silver"
];
$scope.park = function(car) {
car.entrance = new Date();
$scope.cars.push(car);
delete $scope.car;
};
});
</script>
<style>
.selected {
background-color: #FAFAD2;
}
</style>
</head>
<body ng-controller="parkingCtrl">
<h3 ng-bind="appTitle"></h3>
<table>
<thead>
<tr>
<th></th>
<th>Plate</th>
<th>Color</th>
<th>Entrance</th>
</tr>
</thead>
<tbody>
<tr ng-class="{selected: car.selected}" ng-repeat="car in cars">
<td>
<input type="checkbox" ngmodel="car.selected" />
</td>
<td><span ng-bind="car.plate"></span></td>
<td><span ng-bind="car.color"></span></td>
<td><span ng-bind="car.entrance"></span></td>
</tr>
</tbody>
</table>
<input type="text" ng-model="car.plate" placeholder="What's the plate?" />
<select ng-model="car.color" ng-options="color for color in colors">
Pick a color
</select>
<button ng-click="park(car)" ng-disabled="!car.plate || !car.color">
Park
</button>
</body>
</html>
Example
Note the
ng-model="blah" which is saying "set
$scope.blah to the selected value".
<select ng-model="blah" ng-options="item.ID as item.Title for item in items"></select>
Option tag values in Angular
When you use ng-options, the values of option tags written out by ng-options will always be the index of the array item the option tag relates to. This is because Angular actually allows you to select entire objects with select controls, and not just primitive types. For example:
snippet
app.controller('MainCtrl', function($scope) {
$scope.items = [
{ id: 1, name: 'foo' },
{ id: 2, name: 'bar' },
{ id: 3, name: 'blah' }
];
});
<div ng-controller="MainCtrl">
<select ng-model="selectedItem" ng-options="item as item.name for item in items"></select>
<pre>{{selectedItem | json}}</pre>
</div>
The above will allow you to select an entire object into
$scope.selectedItem directly. The point is, with Angular, you don't need to worry about what's in your option tag. Let Angular handle that, you should only care about what's in your model in your scope.
Dealing with the default option
There are a few things to mention above relating to the default option.
Selecting first option and removing the empty option:
You can do this by adding a simple
ng-init
that sets the model (from ng-model) to the first element in the items your repeating in
ng-options
:
<select ng-init="foo = foo || items[0]" ng-model="foo" ng-options="item as item.name for item in items"></select>
Note
Note: this could get a little crazy if foo happens to be initialized properly to something "falsy". In that case, you'll want to handle the initialization of foo in your controller, most likely.
Customizing the default option:
This is a little different, here all you need to do is add an option tag as a child of your select, with an empty value attribute, then customize it's inner text:
<select ng-model="foo" ng-options="item as item.name for item in items">
<option value="">Nothing selected</option>
</select>
Note
Note: that in this case the "empty" option will stay there even after you select a different option. This isn't the case for the default behavior of selects under Angular.
A customized default option that hides after a selection is made:
If you wanted your customized default option to go away after you select a value, you can add an
ng-hide
attribute to your default option:
<select ng-model="foo" ng-options="item as item.name for item in items">
<option value="" ng-if="foo">Select something to remove me.</option>
</select>