Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Commit

Permalink
feat(ngModelOptions): custom triggers and debounce of ngModel updates
Browse files Browse the repository at this point in the history
By default, any change to an input will trigger an immediate model update,
form validation and run a $digest. This is not always desirable, especially
when you have a large number of bindings to update.

This PR implements a new directive `ngModelOptions`, which allow you to
override this default behavior in several ways. It is implemented as an
attribute, to which you pass an Angular expression, which evaluates to an
**options** object.

All inputs, using ngModel, will search for this directive in their ancestors
and use it if found.  This makes it easy to provide options for a whole
form or even the whole page, as well as specifying exceptions for
individual inputs.

* You can specify what events trigger an update to the model by providing
  an `updateOn` property on the **options** object. This property takes a
  string containing a space separated list of events.

  For example, `ng-model-options="{ updateOn: 'blur' }"` will update the
  model only after the input loses focus.

  There is a special pseudo-event, called "default", which maps to the
  default event used by the input box normally. This is useful if you
  want to keep the default behavior and just add new events.

* You can specify a debounce delay, how long to wait after the last triggering
  event before updating the model, by providing a `debounce` property on
  the **options** object.

  This property can be a simple number, the
  debounce delay for all events. For example,
  `ng-model-options="{ debounce: 500 }" will ensure the model is updated
  only when there has been a period 500ms since the last triggering event.

  The property can also be an object, where the keys map to events and
  the values are a corresponding debounce delay for that event.
  This can be useful to force immediate updates on some specific
  circumstances (like blur events). For example,
  `ng-model-options="{ updateOn: 'default blur', debounce: { default: 500, blur: 0} }"`

This commit also brings to an end one of the longest running Pull Requests
in the history of AngularJS (#2129)!  A testament to the patience of @lrlopez.

Closes #1285, #2129, #6945
  • Loading branch information
lrlopez authored and petebacondarwin committed Apr 4, 2014
1 parent e55c8bc commit dbe381f
Show file tree
Hide file tree
Showing 4 changed files with 568 additions and 63 deletions.
76 changes: 76 additions & 0 deletions docs/content/guide/forms.ngdoc
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,82 @@ This allows us to extend the above example with these features:



# Custom triggers

By default, any change to the content will trigger a model update and form validation. You can
override this behavior using the {@link ng.directive:ngModelOptions ngModelOptions} directive to
bind only to specified list of events. I.e. `ng-model-options="{ updateOn: "blur" }"` will update
and validate only after the control loses focus. You can set several events using a space delimited
list. I.e. `ng-model-options="{ updateOn: 'mousedown blur' }"`

If you want to keep the default behavior and just add new events that may trigger the model update
and validation, add "default" as one of the specified events.

I.e. `ng-model-options="{ updateOn: 'default blur' }"`

The following example shows how to override immediate updates. Changes on the inputs within the form will update the model
only when the control loses focus (blur event).

<example>
<file name="index.html">
<div ng-controller="ControllerUpdateOn">
<form>
Name:
<input type="text" ng-model="user.name" ng-model-options="{ updateOn: "blur" }" /><br />
Other data:
<input type="text" ng-model="user.data" /><br />
</form>
<pre>username = "{{user.name}}"</pre>
</div>
</file>
<file name="script.js">
function ControllerUpdateOn($scope) {
$scope.user = {};
}
</file>
</example>



# Non-immediate (debounced) model updates

You can delay the model update/validation by using the `debounce` key with the
{@link ng.directive:ngModelOptions ngModelOptions} directive. This delay will also apply to
parsers, validators and model flags like `$dirty` or `$pristine`.

I.e. `ng-model-options="{ debounce: 500 }"` will wait for half a second since
the last content change before triggering the model update and form validation.

If custom triggers are used, custom debouncing timeouts can be set for each event using an object
in `debounce`. This can be useful to force immediate updates on some specific circumstances
(like blur events).

I.e. `ng-model-options="{ updateOn: 'default blur', debounce: { default: 500, blur: 0 } }"`

If those attributes are added to an element, they will be applied to all the child elements and controls that inherit from it unless they are
overridden.

This example shows how to debounce model changes. Model will be updated only 250 milliseconds after last change.

<example>
<file name="index.html">
<div ng-controller="ControllerUpdateOn">
<form>
Name:
<input type="text" ng-model="user.name" ng-model-options="{ debounce: 250 }" /><br />
</form>
<pre>username = "{{user.name}}"</pre>
</div>
</file>
<file name="script.js">
function ControllerUpdateOn($scope) {
$scope.user = {};
}
</file>
</example>



# Custom Validation

Angular provides basic implementation for most common html5 {@link ng.directive:input input}
Expand Down
4 changes: 3 additions & 1 deletion src/AngularPublic.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
requiredDirective,
requiredDirective,
ngValueDirective,
ngModelOptionsDirective,
ngAttributeAliasDirectives,
ngEventDirectives,
Expand Down Expand Up @@ -183,7 +184,8 @@ function publishExternalAPI(angular){
ngChange: ngChangeDirective,
required: requiredDirective,
ngRequired: requiredDirective,
ngValue: ngValueDirective
ngValue: ngValueDirective,
ngModelOptions: ngModelOptionsDirective
}).
directive({
ngInclude: ngIncludeFillContentDirective
Expand Down
Loading

0 comments on commit dbe381f

Please sign in to comment.