<!doctype html>
<html ng-app="Demo" ng-controller="DemoController">
<head>
	<meta charset="utf-8" />

	<title>
		Mixing Static And Dynamic Options In An AngularJS Select Menu
	</title>
</head>
<body>

	<h1>
		Mixing Static And Dynamic Options In An AngularJS Select Menu
	</h1>

	<form>

		<select
			ng-model="selection"
			ng-options="option.value as option.text for option in options">

			<!-- You can have ONE default, null selection option. -->
			<option value="">- - Make Selection - -</option>

		</select>

		<button type="button" ng-click="selectJoanna()">
			Select Joanna
		</button>

		<button type="button" ng-click="selectNull()">
			Select null
		</button>

	</form>

	<p ng-show="selectedFriend">

		{{ selectedFriend.id }} - {{ selectedFriend.name }}

	</p>



	<!-- Load jQuery and AngularJS from the CDN. -->
	<script
		type="text/javascript"
		src="//code.jquery.com/jquery-1.9.1.min.js">
	</script>
	<script
		type="text/javascript"
		src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js">
	</script>

	<!-- Load the app module and its classes. -->
	<script type="text/javascript">


		// Define our AngularJS application module.
		var demo = angular.module( "Demo", [] );


		// -------------------------------------------------- //
		// -------------------------------------------------- //


		// I am the main controller for the application.
		demo.controller(
			"DemoController",
			function( $scope ) {


				// -- Define Scope Methods. ----------------- //


				// I explicitly select Joanna just to demonstrate how
				// the two-way data binding will behave. Once we
				// select Joanna explicitly, the ngModel will reflect
				// that change in the Select menu.
				$scope.selectJoanna = function() {

					$scope.selection = $scope.friends[ 1 ];

				};


				// One more demo to show how selection will be
				// reflected in two-way data binding.
				$scope.selectNull = function() {

					$scope.selection = null;

				};


				// -- Define Scope Variables. --------------- //


				// I am the "dynamic" data portion of the select menu.
				// Dynamic in the sense that it may have come from a
				// data source and we don't know who big the list is.
				$scope.friends = [
					{
						id: 1,
						name: "Tricia"
					},
					{
						id: 2,
						name: "Joanna"
					},
					{
						id: 3,
						name: "Sarah"
					}
				];


				// I am the "static" data portion of the select menu.
				// This will be hard-coded in our Controller and used
				// to facilitate selection.
				$scope.staticOptions = [
					{
						value: "random",
						text: "Random Friend"
					},
					{
						value: "hrule",
						text: "- - -"
					}
				];


				// When it comes to populating the Select options,
				// we can't simply feed in the collection of friends
				// because, well, that's not what that list is. Sure,
				// it *contains* friends; but, it's NOT a list of
				// friends. As such, we need to create a separate list
				// of options that houses BOTH our dynamic data and
				// our static data.
				//
				// As we do this, we want to map Friend collection
				// onto a collection that mimics the Value/Text
				// structure of our other options. This will make
				// rendering the list easier.
				$scope.options = $scope.staticOptions.concat(
					$.map(
						$scope.friends,
						function( friend ) {

							// NOTE: "Value" here will reference our
							// friend object, which will be mirrored
							// in the selection variable.
							return({
								value: friend,
								text: friend.name
							});

						}
					)
				);


				// Since the select list is NOT just a list of
				// friends, we have to differentiate between our
				// list of friends and our selection.
				$scope.selection = null;
				$scope.selectedFriend = null;


				// -- Define Scope Events. ------------------ //


				// As the select menu changes, it will change our
				// selection. When that happens, we have to map that
				// change onto our Friends collection.
				$scope.$watch(
					"selection",
					function( value ) {

						// No "valid" value was selected.
						if ( value === "hrule" ) {

							// Reset the selection
							$scope.selection = null;

						// A random friend was selected.
						} else if ( value === "random" ) {

							var index = Math.floor( Math.random() * 3 );

							$scope.selection = $scope.friends[ index ];

						// NULL or an actual friend was selected.
						// In either case, we can use the selection
						// value as our selected friend.
						} else {

							$scope.selectedFriend = $scope.selection;

						}

					}
				);


			}
		);


	</script>

</body>
</html>