Skip to content

Commit 4175860

Browse files
committed
docs(ngModel): improve the $setViewValue documentation
- reorder the paragraphs to highlight more important info - clarify what can / should be passed to the method, and what to (not) expect from it - clarify when the method will trigger a digest Closes angular#12713 Closes angular#11121 Closes angular#12498
1 parent 6fb90bd commit 4175860

1 file changed

Lines changed: 30 additions & 20 deletions

File tree

src/ng/directive/ngModel.js

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -728,37 +728,47 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
728728
* @description
729729
* Update the view value.
730730
*
731-
* This method should be called when an input directive want to change the view value; typically,
732-
* this is done from within a DOM event handler.
731+
* This method should be called when a control wants to change the view value; typically,
732+
* this is done from within a DOM event handler. For example, the {@link ng.directive:input input}
733+
* directive calls it when the value of the input changes and {@link ng.directive:select select}
734+
* calls it when an option is selected.
733735
*
734-
* For example {@link ng.directive:input input} calls it when the value of the input changes and
735-
* {@link ng.directive:select select} calls it when an option is selected.
736-
*
737-
* If the new `value` is an object (rather than a string or a number), we should make a copy of the
738-
* object before passing it to `$setViewValue`. This is because `ngModel` does not perform a deep
739-
* watch of objects, it only looks for a change of identity. If you only change the property of
740-
* the object then ngModel will not realise that the object has changed and will not invoke the
741-
* `$parsers` and `$validators` pipelines.
742-
*
743-
* For this reason, you should not change properties of the copy once it has been passed to
744-
* `$setViewValue`. Otherwise you may cause the model value on the scope to change incorrectly.
745-
*
746-
* When this method is called, the new `value` will be staged for committing through the `$parsers`
736+
* When `$setViewValue` is called, the new `value` will be staged for committing through the `$parsers`
747737
* and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged
748738
* value sent directly for processing, finally to be applied to `$modelValue` and then the
749-
* **expression** specified in the `ng-model` attribute.
750-
*
751-
* Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.
739+
* **expression** specified in the `ng-model` attribute. Lastly, all the registered change listeners,
740+
* in the `$viewChangeListeners` list, are called.
752741
*
753742
* In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn`
754743
* and the `default` trigger is not listed, all those actions will remain pending until one of the
755744
* `updateOn` events is triggered on the DOM element.
756745
* All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions}
757746
* directive is used with a custom debounce for this particular event.
747+
* Note that a `$digest` is only triggered once the `updateOn` events are fired, or if `debounce`
748+
* is specified, once the timer runs out.
749+
*
750+
* When used with standard inputs, the view value will always be a string (which is in some cases
751+
* parsed into another type, such as a `Date` object for `input[date]`.)
752+
* However, custom controls might also pass objects to this method. In this case, we should make
753+
* a copy of the object before passing it to `$setViewValue`. This is because `ngModel` does not
754+
* perform a deep watch of objects, it only looks for a change of identity. If you only change
755+
* the property of the object then ngModel will not realise that the object has changed and
756+
* will not invoke the `$parsers` and `$validators` pipelines. For this reason, you should
757+
* not change properties of the copy once it has been passed to `$setViewValue`.
758+
* Otherwise you may cause the model value on the scope to change incorrectly.
758759
*
759-
* Note that calling this function does not trigger a `$digest`.
760+
* <div class="alert alert-info">
761+
* In any case, the value passed to the method should always reflect the current value
762+
* of the control. For example, if you are calling `$setViewValue` for an input element,
763+
* you should pass the input DOM value. Otherwise, the control and the scope model become
764+
* out of sync. It's also important to note that `$setViewValue` does not call `$render` or change
765+
* the control's DOM value in any way. If we want to change the control's DOM value
766+
* programmatically, we should update the `ngModel` scope expression. Its new value will be
767+
* picked up by the model controller, which will run it through the `$formatters`, `$render` it
768+
* to update the DOM, and finally call `$validate` on it.
769+
* </div>
760770
*
761-
* @param {string} value Value from the view.
771+
* @param {*} value value from the view.
762772
* @param {string} trigger Event that triggered the update.
763773
*/
764774
this.$setViewValue = function(value, trigger) {

0 commit comments

Comments
 (0)