@@ -1855,7 +1855,15 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
1855
1855
} ;
1856
1856
1857
1857
this . $$writeModelToScope = function ( ) {
1858
- ngModelSet ( $scope , ctrl . $modelValue ) ;
1858
+ var getterSetter ;
1859
+
1860
+ if ( ctrl . $options && ctrl . $options . getterSetter &&
1861
+ isFunction ( getterSetter = ngModelGet ( $scope ) ) ) {
1862
+
1863
+ getterSetter ( ctrl . $modelValue ) ;
1864
+ } else {
1865
+ ngModelSet ( $scope , ctrl . $modelValue ) ;
1866
+ }
1859
1867
forEach ( ctrl . $viewChangeListeners , function ( listener ) {
1860
1868
try {
1861
1869
listener ( ) ;
@@ -1930,6 +1938,10 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
1930
1938
$scope . $watch ( function ngModelWatch ( ) {
1931
1939
var modelValue = ngModelGet ( $scope ) ;
1932
1940
1941
+ if ( ctrl . $options && ctrl . $options . getterSetter && isFunction ( modelValue ) ) {
1942
+ modelValue = modelValue ( ) ;
1943
+ }
1944
+
1933
1945
// if scope model value and ngModel value are out of sync
1934
1946
if ( ctrl . $modelValue !== modelValue &&
1935
1947
( isUndefined ( ctrl . $$invalidModelValue ) || ctrl . $$invalidModelValue != modelValue ) ) {
@@ -2062,6 +2074,55 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
2062
2074
</form>
2063
2075
</file>
2064
2076
* </example>
2077
+ *
2078
+ * ## Binding to a getter/setter
2079
+ *
2080
+ * Sometimes it's helpful to bind `ngModel` to a getter/setter function. A getter/setter is a
2081
+ * function that returns a representation of the model when called with zero arguments, and sets
2082
+ * the internal state of a model when called with an argument. It's sometimes useful to use this
2083
+ * for models that have an internal representation that's different than what the model exposes
2084
+ * to the view.
2085
+ *
2086
+ * <div class="alert alert-success">
2087
+ * **Best Practice:** It's best to keep getters fast because Angular is likely to call them more
2088
+ * frequently than other parts of your code.
2089
+ * </div>
2090
+ *
2091
+ * You use this behavior by adding `ng-model-options="{ getterSetter: true }"` to an element that
2092
+ * has `ng-model` attached to it. You can also add `ng-model-options="{ getterSetter: true }"` to
2093
+ * a `<form>`, which will enable this behavior for all `<input>`s within it. See
2094
+ * {@link ng.directive:ngModelOptions `ngModelOptions`} for more.
2095
+ *
2096
+ * The following example shows how to use `ngModel` with a getter/setter:
2097
+ *
2098
+ * @example
2099
+ * <example name="ngModel-getter-setter" module="getterSetterExample">
2100
+ <file name="index.html">
2101
+ <div ng-controller="ExampleController">
2102
+ <form name="userForm">
2103
+ Name:
2104
+ <input type="text" name="userName"
2105
+ ng-model="user.name"
2106
+ ng-model-options="{ getterSetter: true }" />
2107
+ </form>
2108
+ <pre>user.name = <span ng-bind="user.name()"></span></pre>
2109
+ </div>
2110
+ </file>
2111
+ <file name="app.js">
2112
+ angular.module('getterSetterExample', [])
2113
+ .controller('ExampleController', ['$scope', function($scope) {
2114
+ var _name = 'Brian';
2115
+ $scope.user = {
2116
+ name: function (newName) {
2117
+ if (angular.isDefined(newName)) {
2118
+ _name = newName;
2119
+ }
2120
+ return _name;
2121
+ }
2122
+ };
2123
+ }]);
2124
+ </file>
2125
+ * </example>
2065
2126
*/
2066
2127
var ngModelDirective = function ( ) {
2067
2128
return {
@@ -2459,6 +2520,8 @@ var ngValueDirective = function() {
2459
2520
* value of 0 triggers an immediate update. If an object is supplied instead, you can specify a
2460
2521
* custom value for each event. For example:
2461
2522
* `ngModelOptions="{ updateOn: 'default blur', debounce: {'default': 500, 'blur': 0} }"`
2523
+ * - `getterSetter`: boolean value which determines whether or not to treat functions bound to
2524
+ `ngModel` as getters/setters.
2462
2525
*
2463
2526
* @example
2464
2527
@@ -2541,6 +2604,33 @@ var ngValueDirective = function() {
2541
2604
}]);
2542
2605
</file>
2543
2606
</example>
2607
+
2608
+ This one shows how to bind to getter/setters:
2609
+
2610
+ <example name="ngModelOptions-directive-getter-setter" module="getterSetterExample">
2611
+ <file name="index.html">
2612
+ <div ng-controller="ExampleController">
2613
+ <form name="userForm">
2614
+ Name:
2615
+ <input type="text" name="userName"
2616
+ ng-model="user.name"
2617
+ ng-model-options="{ getterSetter: true }" />
2618
+ </form>
2619
+ <pre>user.name = <span ng-bind="user.name()"></span></pre>
2620
+ </div>
2621
+ </file>
2622
+ <file name="app.js">
2623
+ angular.module('getterSetterExample', [])
2624
+ .controller('ExampleController', ['$scope', function($scope) {
2625
+ var _name = 'Brian';
2626
+ $scope.user = {
2627
+ name: function (newName) {
2628
+ return angular.isDefined(newName) ? (_name = newName) : _name;
2629
+ }
2630
+ };
2631
+ }]);
2632
+ </file>
2633
+ </example>
2544
2634
*/
2545
2635
var ngModelOptionsDirective = function ( ) {
2546
2636
return {
0 commit comments