How to use ng-model-options for delayed model updates?

Loading

In AngularJS, ng-model is used for two-way data binding, where the model updates instantly when the user types in an input field. However, in some cases, instant updates are not ideal, such as:

  • Reducing API calls when fetching data from a server (e.g., search autocomplete).
  • Improving performance by minimizing unnecessary digest cycle updates.
  • Waiting for user input completion before processing data.

To handle these scenarios, AngularJS provides ng-model-options, which allows developers to control when and how model updates occur.


Step 1: Understanding ng-model-options

The ng-model-options directive lets you customize the behavior of ng-model. It provides options like:

  • debounce → Delays model updates after user stops typing.
  • updateOn → Specifies events that trigger model updates (e.g., blur, keydown).
  • getterSetter → Enables using functions as model bindings.
  • allowInvalid → Allows invalid values to be stored in the model.

Step 2: Using ng-model-options for Delayed Updates

Basic Example – Using debounce

Let’s see how debounce works by introducing a 500ms delay in updating the model.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ng-model-options Example</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body ng-app="app" ng-controller="MainController">

<h2>Search Box with Delay (500ms)</h2>
<input type="text" ng-model="searchQuery" ng-model-options="{ debounce: 500 }">

<p>Search Query: {{ searchQuery }}</p>

</body>
<script>
var app = angular.module("app", []);

app.controller("MainController", function($scope) {
$scope.searchQuery = "";
});
</script>
</html>

How This Works

  • The debounce: 500 ensures the model (searchQuery) updates only after 500ms of inactivity.
  • If the user types continuously, AngularJS waits until they stop for 500ms before updating the searchQuery model.

Use case: Prevents frequent API calls when typing in a live search box.


Step 3: Using updateOn to Change Update Trigger

By default, AngularJS updates the model on every keystroke (input event).
Using updateOn, we can delay updates until a specific event like blur (when the user moves away from the input field).

<input type="text" ng-model="username" ng-model-options="{ updateOn: 'blur' }">
<p>Username: {{ username }}</p>

How This Works

  • The model only updates when the user leaves the input field (blur event).
  • It prevents real-time updates and reduces performance overhead.

Use case: Useful for form validation, where the input should be validated only after the user finishes typing.


Step 4: Combining debounce and updateOn

We can combine debounce and updateOn for even better control.

<input type="text" ng-model="comment" ng-model-options="{ updateOn: 'blur keydown', debounce: { keydown: 300, blur: 0 } }">
<p>Comment: {{ comment }}</p>

How This Works

  • The model updates:
    • On blur (when the user leaves the input field) immediately.
    • On keydown after 300ms (if the user stops typing for 300ms).
  • This ensures a smooth user experience, combining instant updates on blur with delayed updates during typing.

Use case: Ideal for chat applications, where messages should send when typing pauses or when a user moves focus.


Step 5: Using getterSetter for Function-Based Models

Sometimes, we may want custom logic when reading/writing data. The getterSetter option allows the model to be a function instead of a variable.

<input type="text" ng-model="getSetModel" ng-model-options="{ getterSetter: true }">
<p>Value: {{ getSetModel() }}</p>

Controller:

app.controller("MainController", function($scope) {
var value = "Hello";

$scope.getSetModel = function(newValue) {
if (angular.isDefined(newValue)) {
value = newValue.toUpperCase(); // Converts input to uppercase
}
return value;
};
});

How This Works

  • If getSetModel() is called with a value (newValue), it updates value with uppercase conversion.
  • Otherwise, it returns value.

Use case: Useful for custom input processing like formatting, transformations, or API-based storage.


Step 6: Preventing Invalid Values with allowInvalid

By default, AngularJS removes invalid values (like non-numeric input in a number field).
Setting allowInvalid: true allows storing invalid values without breaking the model.

<input type="number" ng-model="age" ng-model-options="{ allowInvalid: true }">
<p>Age: {{ age }}</p>

How This Works

  • Normally, if the user enters a non-numeric value, AngularJS removes it.
  • With allowInvalid: true, invalid inputs are preserved (though they may not be usable elsewhere).

Use case: Helps in scenarios where users enter partial values (e.g., entering “12e” in a number field before completing it as “12”).


Conclusion

Using ng-model-options, we can fine-tune AngularJS’ model behavior to optimize performance and user experience. Here’s a recap:

FeatureExampleUse Case
Debounce{ debounce: 500 }Reducing API calls, live search
UpdateOn{ updateOn: 'blur' }Delayed validation, better UX
Debounce + UpdateOn{ updateOn: 'blur keydown', debounce: { keydown: 300, blur: 0 } }Forms & real-time validation
GetterSetter{ getterSetter: true }Custom logic for input handling
AllowInvalid{ allowInvalid: true }Handling incomplete inputs

Mastering ng-model-options helps developers control how user input is processed, improving performance, usability, and efficiency in AngularJS applications.

Leave a Reply

Your email address will not be published. Required fields are marked *