Created
July 9, 2013 13:52
What A Select $watch() Teaches Me About ngModel And AngularJS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html ng-app="Demo" ng-controller="AppController"> | |
<head> | |
<meta charset="utf-8" /> | |
<title> | |
What A Select $watch() Teaches Me About ngModel And AngularJS | |
</title> | |
</head> | |
<body> | |
<h1> | |
What A Select $watch() Teaches Me About ngModel And AngularJS | |
</h1> | |
<p> | |
Helena Bonham Carter is {{ helena.quality }}! | |
</p> | |
<!-- Set value via Select / ngOptions. --> | |
<p> | |
<select | |
ng-model="form.quality" | |
ng-options="q.label for q in qualities"> | |
</select> | |
</p> | |
<!-- Set value explicitly on data-model. --> | |
<p> | |
<a ng-click="setStunning()">Stunning</a> or | |
<a ng-click="setBeautiful()">Beautiful</a> | |
</p> | |
<!-- Load jQuery and AngularJS from the CDN. --> | |
<script | |
type="text/javascript" | |
src="//code.jquery.com/jquery-2.0.0.min.js"> | |
</script> | |
<script | |
type="text/javascript" | |
src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"> | |
</script> | |
<script type="text/javascript"> | |
// Create an application module for our demo. | |
var app = angular.module( "Demo", [] ); | |
// -------------------------------------------------- // | |
// -------------------------------------------------- // | |
// I control the root of the application. | |
app.controller( | |
"AppController", | |
function( $scope ) { | |
// I define the initial state of Helena. | |
$scope.helena = { | |
name: "Helena", | |
quality: "beautiful" | |
}; | |
// I define the possible qualities that can be | |
// selected in the dropdown menu. | |
$scope.qualities = [ | |
{ | |
label: "Beautiful", | |
value: "beautiful" | |
}, | |
{ | |
label: "Stunning", | |
value: "simply stunning" | |
}, | |
{ | |
label: "Dark", | |
value: "dark and mysterious" | |
}, | |
{ | |
label: "Exotic", | |
value: "exotic" | |
}, | |
{ | |
label: "Silly (disabled)", | |
value: "silly" | |
} | |
]; | |
// I set up the initial form values for the ngModel | |
// bindings. This allows me to examine the form values | |
// before I *choose* to have the changes propagated | |
// throughout my view-model. | |
$scope.form = { | |
quality: getQualityOptionByValue( "beautiful" ) | |
}; | |
// I watch the data-model for changes such that I may | |
// synchronize the form values. | |
$scope.$watch( | |
"helena.quality", | |
function( newValue, oldValue ) { | |
// Ignore initial setup. | |
if ( newValue === oldValue ) { | |
return; | |
} | |
console.log( "$watch: helena.quality changed." ); | |
// Ignore if form already mirrors new value. | |
if ( $scope.form.quality.value === newValue ) { | |
return; | |
} | |
$scope.form.quality = getQualityOptionByValue( newValue ); | |
} | |
); | |
// I watch the form for changes such that I may | |
// synchronize the data-model. | |
$scope.$watch( | |
"form.quality", | |
function( newValue, oldValue ) { | |
// Ignore initial setup. | |
if ( newValue === oldValue ) { | |
return; | |
} | |
console.log( "$watch: form.quality changed." ); | |
// Ignore if the data-model already mirrors | |
// the new value defined in the form. | |
if ( $scope.helena.quality === newValue.value ) { | |
return; | |
} | |
// Ignore "invalid" form selection. This isn't | |
// a likely use-case; however, it does point | |
// out a possible benefit of this two-way | |
// data-binding gatekeeper. | |
if ( newValue.value === "silly" ) { | |
// Reset to the old value!!! | |
return( $scope.form.quality = oldValue ); | |
} | |
$scope.helena.quality = newValue.value; | |
} | |
); | |
// --- | |
// PUBLIC METHODS. | |
// --- | |
// I define Helena as beautiful. | |
$scope.setBeautiful = function() { | |
$scope.helena.quality = "beautiful"; | |
}; | |
// I define Helena as stunning! | |
$scope.setStunning = function() { | |
$scope.helena.quality = "simply stunning"; | |
}; | |
// --- | |
// PRIVATE METHODS. | |
// --- | |
// I return the select-option with the given value. | |
function getQualityOptionByValue( value ) { | |
for ( var i = 0 ; i < $scope.qualities.length ; i++ ) { | |
if ( $scope.qualities[ i ].value === value ) { | |
return( $scope.qualities[ i ] ); | |
} | |
} | |
return( null ); | |
} | |
} | |
); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment