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

I have a task of extracting information from a live Google map and generating a static Google map using API V3

I am working on a project that involves allowing users to create maps using Google Maps and then save the image. My current workaround uses both the Google Maps API V3 and the Static Maps API. The user can interact with the dynamic Google map by scrolling ...

An AJAX event handling function returns a null value upon invocation

Recently, I've been working on a function named 'getAuthor' which includes an AJAX event. Here's the code snippet: function getAuthor(id){ $.get('http://www.connectnigeria.com/articles/wp-json/wp/v2/users/74',function(e){ ...

retrieve data for chart from an AJAX request

I am looking to create a chart using amCharts and I have received some values from the server through an ajax call. Now, I need help in utilizing this data for my chart. Can anyone guide me on how to achieve this? var chart = am4core.create("chartdiv& ...

Exploring Laravel and Angular: A guide to serving the complete public directory for single page application requirements

Exploring the integration of Laravel and Angular for a single page app has led me to numerous tutorials, each presenting its own unique approach to adjusting the public directory or using the File helper for file forwarding. Currently, I have modified my ...

What is the purpose of the .default() method being added to the class constructor in transpiled Typescript code

In TypeScript, I have the following code snippet to create an instance of ConnectRoles Middleware in Express: let user = new ConnectRoles(config); The middleware initialization is expected to be a simple call to a constructor. However, after transpiling, ...

Display personalized content over images utilizing the jQuery galleria plugin

Hey there, I've been successfully using the jquery galleria plugin, but now I'm looking to add some custom content and links that will display in the center of the image. Is it possible to achieve this with galleria? Your insights would be greatl ...

Oops! An error occurred while trying to find the _mongodb._tcp.blog-cluster-0hb5z.mongodb.net. Please check your query settings and try again

My free Mongo Atlas cluster suddenly stopped connecting, even though everything was working fine before. Strangely, I can see that data has been collected on the MongoDB website. It's puzzling why this issue occurred and now my entire site won't ...

Stop Stripe checkout if all other fields are left empty

I am working on a simple "booking" function using stripe and I encountered this issue. Below is my form code: <form id="formid" action="/checkout" method="POST"> <input type="text" name="kurtuma" id="zaza"> <script src="//check ...

Enhancing jQuery Rating Plugin

Currently, I am working on customizing the jQuery Bar Rating System Plugin. You can view an example of the plugin by visiting this link: . The rating system on my end will resemble Example D. Rather than having the plugin based on user input, my goal is to ...

Is it possible to pass an AngularJS ng-form object as a parameter in ng-if?

When I try to preview, the save button in my preview mode remains enabled. You can view the code snippet here: http://plnkr.co/edit/I3n29LHP2Yotiw8vkW0i I believe this issue arises because the form object (testAddForm) is not accessible within the ng-if s ...

What is the process for including an additional button in the DateTimePicker feature of material UI?

I'm currently utilizing DateTimePicker in my React application. I wish to incorporate a Clear button positioned to the left of the Cancel Button. import { MuiPickersUtilsProvider, DateTimePicker } from "@material-ui/pickers"; import DateFnsUtils fro ...

A dynamic substitute for the Supersized slideshow option

I am in the process of updating my website and the final task on my to-do list is to replace the Supersized plugin with a more suitable alternative. The website is constructed using WordPress and I am utilizing jQuery. My goal is to find a fullscreen slid ...

Refresh the page with cleared cache using window.location.reload

Is there a way to reload a page using JavaScript and still clear the cache, ensuring that the refreshed page shows the latest content from the server? It seems that other browsers are not displaying the most up-to-date versions of the content. Anyone have ...

Identify when users reach the end of a webpage through scrolling using mousewheel actions and scroll events

I want to track when a user reaches the end of a page and tries to scroll further, even though there is no more content to see. One of my usability metrics includes identifying dead scrolls, so I need a reliable way to detect when users attempt to scroll ...

Material UI - Array of Chips

I have been working on creating a ReactJS component that displays an array of chips with unique styling for each one. To achieve this, I created individual makeStyles classes for the chips. However, I encountered difficulties in dynamically changing the cl ...

Animate the transition effect as soon as the block is displayed

Looking to create a smooth page transition using CSS changes with the help of Javascript (jQuery). Initially, one of the pages is set to display none. page1 = $('.page1'); page2 = $('.page2'); page1.removeClass('animate').cs ...

Encountering a sanity issue while attempting to execute vercel build: sanity/..page.jsx lacks a root layout. To resolve this issue, ensure that each page includes a root layout

While my project runs smoothly locally, I encounter issues when trying to deploy it on Vercel. The error message reads: ⨯ sanity/[[...index]]/page.jsx doesn't have a root layout. To resolve this issue, ensure that every page has a root layout. Comp ...

Regular expression for precise numerical values of a specific magnitude (any programming language)

I have been searching for a solution to what I thought was a common problem but haven't found one yet. What I need is a regular expression that will fail on a specific number of significant figures (a Max), but pass for fewer than the Max. It should ...

Exploring creative solutions for generating PDFs with Node JS

Looking for a way to generate PDF Documents in Node.JS? Is there an alternative solution for organizing templates for various types of PDF creation? I've been utilizing PDFKit for creating PDF Documents on the server side with Javascript. Unfortunate ...

What is the best way to access props from a different file in a React application?

I am facing a challenge with my two files: EnhancedTableHead and OrderDialog. I need to access the props data from EnhancedTabledHead in my OrderDialog file. Is there a way to achieve this? Here is how my files are structured: //OrderDialog.jsx import ...