Debouncing in AngularJS with $watch

In my code, I have an HTML search field represented by the following:

<input ng-model-options="{ debounce: 500 }" type="text" ng-model="name">

Along with the JavaScript snippet:

$scope.$watch('name', function(newVal, oldVal) {
            if(newVal != oldVal) {
                $scope.pageChanged($scope.sort, $scope.name, $scope.sortDirection);
            }
        });

The challenge I am facing is related to avoiding multiple REST calls when a user searches for something like "Tom." Making separate calls for each incremental search term (T, To, Tom) is not efficient. I initially tried using debounce, but it seems that watch doesn't play well with it. I'm now exploring ways to achieve this functionality with minimal code. Any suggestions?

Answer №1

In situations like this, it is recommended to utilize ng-change instead of setting up a watch.

<input ng-model-options="{ debounce: 500 }" type="text" ng-model="name" ng-change="modelChanged()">

JavaScript:

var timeout = $timeout(function(){});

$scope.modelChanged = function(){
    $timeout.cancel(timeout); //cancel the previous timeout
    timeout = $timeout(function(){
        $scope.pageChanged($scope.sort, $scope.name, $scope.sortDirection);
    }, 500);
};

I'm not very familiar with debounce, but it may serve the same purpose.

Answer №2

Interesting Approach to Handling the Issue!

Resolution:

To address a similar problem, I devised a solution by incorporating the debounce function into a service inspired by lodash's implementation. For reference, you can find an example of this implementation in this StackOverflow post (referencing @Pete BD's response).

// Setting up an AngularJS service named debounce
app.factory('debounce', ['$timeout','$q', function($timeout, $q) {
  // The actual service is defined as a function that takes in the target function and wait time
  return function debounce(func, wait, immediate) {
    var timeout;
    // Creating a deferred object for resolution when it's time to call the func
    var deferred = $q.defer();
    return function() {
      var context = this, args = arguments;
      var later = function() {
        timeout = null;
        if(!immediate) {
          deferred.resolve(func.apply(context, args));
          deferred = $q.defer();
        }
      };
      var callNow = immediate && !timeout;
      if ( timeout ) {
        $timeout.cancel(timeout);
      }
      timeout = $timeout(later, wait);
      if (callNow) {
        deferred.resolve(func.apply(context,args));
        deferred = $q.defer();
      }
      return deferred.promise;
    };
  };
}]);

Once set up, I integrated this service within my controller/directive utilizing $watch and applied it following your provided code snippet:

$scope.$watch('name', debounce(function(newVal, oldVal) {
   if(newVal != oldVal) {
     $scope.pageChanged($scope.sort, $scope.name, $scope.sortDirection);
   }
}, 500));

Problem Solved!


Case Background:

Additionally, I experimented with the following approach:

$scope.$watch('name', function(newVal, oldVal) {

   debounce(function() {
     if(newVal != oldVal) {
       $scope.pageChanged($scope.sort, $scope.name, $scope.sortDirection);
     },500)();
});

However, I faced dissatisfaction as the watch was triggered twice within 50ms.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issues with routeparams are preventing ng-repeat from functioning properly, without any response or resolution

For my shoppingCart project, I am working on dynamically bringing data into views. I am using routeParams in template.html but facing an issue. The data is arriving normally as checked via ng-href="#/store/{{something.name}}/{{ child.name }}" but it isn&ap ...

The requested URL socket.io/1/?t= cannot be located

I've created a web application running on rails 4 at localhost:3000. A client-side angularjs is also incorporated into the project. The socket.io.js file has been placed in the public folder of my rails app. In my angularjs client code, I have the fol ...

Can you explain the concept of System.register in a JavaScript file?

Can you explain the purpose of System.register in a JS file when utilizing directives in Angular 2? ...

Loading Collada files with a progress callback function can help track the

Is there a proper way to incorporate a loading bar while using the ColladaLoader? The code indicates that the loader requires three parameters, with one being a progressCallback. progressCallback( { total: length, loaded: request.responseText.length } ); ...

Prevent zooming or controlling the lens in UIWebview while still allowing user selection

Is there a way to disable the zoom/lens on uiwebview without affecting user selection? I'm trying to avoid using "-webkit-user-select:none" in my css. -webkit-user-select:none ...

Having trouble with JSON parsing in Promise execution

I am in the process of developing a Promise with the objective of adding up any numbers discovered within an array or JSON object. The add() function is designed to receive a series of URLs as a string input and calculate the total sum of those URLs. Her ...

Is there a way to retrieve all active HTTP connections on my Express.js server?

In my express server app, I am implementing SSE (server send events) to inform clients about certain events. Below is the code snippet from my server: sseRouter.get("/stream", (req, res) => { sse.init(req, res); }); let streamCount = 0; class SS ...

Challenge encountered when attempting to remove elements from an array within a for loop

There seems to be an issue with deleting elements from an array within a for loop. var div = document.querySelector('div'); var array = [ "iPad", "iPod", "iPhone" ]; for (let i = 0; i < array.length; i++) { let p = document.createElement ...

When using Firestore in Android, I encounter a nodejs error regarding headers being sent prematurely

Currently, I am utilizing a webview in order to display content from a nodejs server. While requesting a page works as expected, accessing firestore results in an error where it seems like nodejs is attempting to resend the page. Below is the code for an a ...

Display or conceal div elements using JavaScript

Is there a way to hide certain divs when clicking on a specific div box? Clicking on the box will trigger the hiding of some application divs. See the first image below: When the boxes are hidden, the other divs will readjust in place of the current divs ...

Implementing a loop in JSON with Angular: A step-by-step guide

I have a task to generate a JSON structure that looks like the following: "combinationsData":[ { "combinationName":"2_2", "dataGroups": [ { "tableType":"2",//This value comes from HTML "twoAxisDat ...

Shifting / Prepending to the Beginning of Firebase Object with AngularFire or Plain JavaScript

I've been using AngularFire to add items to an array / object stored on Firebase by utilizing the $add function. This function works similarly to the .push method in regular JavaScript, as it adds the specified value to the end of the array. However, ...

Tips for adding an array to a formData: incorporating an array with two values along with their corresponding keys

Snippet : const options = new RequestOptions({ headers: headers }); let myArray; myArray = [{ "subfolder_name": subfolder, "file_upload": file }]; let formData: FormData = new FormData(); formData.append("folder_name",folder ); formData.append("counse ...

I encountered a "Bad Request" error when trying to login through my nodejs server, and I'm unsure of the reason behind this issue. As a beginner in nodejs, I'm still learning the ins and

passport.use(new LocalStrategy(async(email,password,done) => {    try{     const user = await User.findOne({email:email})     if(!user){        return done(null,false,{message:"Invalid email"})     }     const isValidPassword =aw ...

Issue with Angular 12 service worker causing SW update to fail

I'm currently working on integrating a service worker into my Angular application to enable updates without user intervention. Here is the step-by-step process that I am following: Make changes to the application Run ng build Start an HTTP ser ...

Two draggable elements and two droppable containers all conveniently placed on a single webpage

My current project involves two sets of draggable elements and two sets of droppable elements. I'm trying to achieve a specific functionality where the first set of draggable elements can only be dropped inside the first set of droppables, while the ...

Discovering details regarding cookies established by an external domain

Is it possible to retrieve the host address of the domain that created a cookie on my webpage? Here is the scenario I am facing: I am on "domain A" and have a script linked from "domain B". A method on "domain B" sets a cookie on my "domain A". How can ...

Is it possible to use a Backbone Model for an unconventional HTTP POST request that isn't

After going through the documentation at and , I tried to make an HTTP POST request to fetch some JSON data for my model. However, due to the services not being RESTful, I ended up using a POST request instead of a GET request. The code snippet I have co ...

Tips for resizing an image to perfectly fit on a compact HTML5 canvas without sacrificing its quality

I need assistance with my code. I'm trying to draw an image on the canvas while maintaining its quality. const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); canvas.width = 360px; canvas.height = 360px; const img ...

Is there a way to incorporate additional text into option text without compromising the existing values?

One challenge I'm facing is adding additional text to the options without changing their values upon selection. Would you be able to assist me with resolving this issue? I have come across the following HTML code: <select id="q_c_0_a_0_name"> ...