From 2e84cf92745d006c54bb22042bed1845dbc78710 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Wed, 9 Jul 2014 14:54:09 +0100 Subject: [PATCH] docs(ngModel): further mods to $viewValue semantics Closes #8110 --- src/ng/directive/input.js | 42 +++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index 3b8d3d7a..bf3111e8 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -1577,9 +1577,19 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ * * @description * Called when the view needs to be updated. It is expected that the user of the ng-model - * directive will implement this method. Note that in case `$modelValue` is an object, - * this method will be invoked only if a different instance is assigned to the model since - * `ngModel` does not perform a deep watch of objects. + * directive will implement this method. + * + * The `$render()` method is invoked in the following situations: + * + * * `$rollbackViewValue()` is called. If we are rolling back the view value to the last + * committed value then `$render()` is called to update the input control. + * * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and + * the `$viewValue` are different to last time. + * + * Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of + * `$modelValue` and `$viewValue` are actually different to their previous value. If `$modelValue` + * or `$viewValue` are objects (rather than a string or number) then `$render()` will not be + * invoked if you only change a property on the objects. */ this.$render = noop; @@ -1880,15 +1890,25 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ * @description * Update the view value. * - * This method should be called when the view value changes, typically from within a DOM event handler. - * For example {@link ng.directive:input input} and {@link ng.directive:select select} - * directives call it. In case the view value is an object, this method should be called with a - * copy of that object since `ngModel` does not perform a deep watch of objects. Properties of - * that copy should not be changed after `$setViewValue` in invoked. + * This method should be called when an input directive want to change the view value; typically, + * this is done from within a DOM event handler. * - * It will update the $viewValue, then pass this value through each of the functions in `$parsers`, - * which includes any validators. The value that comes out of this `$parsers` pipeline, be applied to - * `$modelValue` and the **expression** specified in the `ng-model` attribute. + * For example {@link ng.directive:input input} calls it when the value of the input changes and + * {@link ng.directive:select select} calls it when an option is selected. + * + * If the new `value` is an object (rather than a string or a number), we should make a copy of the + * object before passing it to `$setViewValue`. This is because `ngModel` does not perform a deep + * watch of objects, it only looks for a change of identity. If you only change the property of + * the object then ngModel will not realise that the object has changed and will not invoke the + * `$parsers` and `$validators` pipelines. + * + * For this reason, you should not change properties of the copy once it has been passed to + * `$setViewValue`. Otherwise you may cause the model value on the scope to change incorrectly. + * + * When this method is called, the new `value` will be staged for committing through the `$parsers` + * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged + * value sent directly for processing, finally to be applied to `$modelValue` and then the + * **expression** specified in the `ng-model` attribute. * * Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called. *