Executing a function within ng-repeat loop four times in AngularJs

In the code snippet below, a ul is populated with 21 phones using HTML:

<li ng-repeat="phone in phones" ng-class="{'digestTest': countDigestOccurences(phone) }">
  <p>{{phone.snippet}}</p>
</li>

The JavaScript method countDigestOccurences utilizes a dictionary to track the number of times it is called for each phone:

$scope.countDigestOccurences = function(phone){
  var phoneFound = false;     
  $.each($scope.digestOccurencesPerPhone, function(){
      if(this.phone.id == phone.id){
        phoneFound = true;
        this.occurences++;
      }
  });

  if(!phoneFound)
  { 
    $scope.digestOccurencesPerPhone.push({
      phone: phone,
      occurences: 1
    });
  }
}

Upon analyzing, it is noted that countDigestOccurences is called 4 times for each phone. Curiously, the reason behind this frequent calling remains a mystery.

https://i.sstatic.net/4FL4F.png

Update:

Interestingly, the cycle repeats 4 times even when the Phone item's HTML is modified as shown below:

    <li ng-repeat="phone in phones "
        class="thumbnail phone-listing" ng-class="{ 'digestTest': countDigestOccurences(phone),  'digestTestAgain': randomMethodDoesNothing() }">
      <p>{{phone.snippet}}</p>
    </li>

Answer №1

When Angular compiles and encounters an expression in the view, such as ng-class="function()" or ng-model="toto", a $watch is set up for it. During each digest cycle, Angular checks these watches for any changes in the model.

Within your ng-repeat, there are: one watch on the phones collection, one watch on each phone instance, and one watch on the function. Since the function in the view isn't a scope variable, Angular cannot determine if its result has changed (maybe another scope variable was modified within the function). Therefore, it reevaluates the function result in each digest cycle.

So, you have watches for phones, phone, the function, and the last digest cycle to ensure everything is in order: a total of 4 cycles.

A recommended practice is to avoid using functions in the view unless absolutely necessary. Instead, store the function result in a scope variable and display that variable in the view.

Update:

Following the discussion below, it's important to note that only one watch is created for the ng-class directive, focusing on the value of ng-class. For example, with

ng-class="{'toto' : functionOne(), 'titi' : functionTwo()}"
, the watch is on:
{'toto' : functionOne(), 'titi' : functionTwo()}
. This is based on the AngularJS directive code:
scope.$watch(attr[name], ngClassWatchAction, true);

Answer №2

How many AJAX requests have you made using $http? Each request triggers a $digest cycle. Additionally, when new data arrives and changes occur, another $digest cycle is initiated to ensure comprehensive coverage.

To prevent this, incorporate a boolean variable within an ng-if on a higher-level element and set it to true only after all AJAX requests have been completed (consider using $q).

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

Display event using Angular

I am currently working on an Angular project where I need to print a specific area of the page. While I know that this can be done using media CSS, it is causing issues for me due to the numerous print functionalities present in the project. I am attemptin ...

Converting an array into a string, transitioning from PHP to JavaScript

Hey everyone, I'm currently working on passing an array to a JavaScript file and encountering this error: An exception has been thrown during the rendering of a template ("Notice: Array to string conversion"). What I need is: data: ['2017/7&a ...

Discover how to retrieve the calculated percentage within CSS with the assistance of jQuery specifically designed for Webkit

I'm currently working on a simple sliding animation. However, the div that slides in is utilizing percentages for its width and right positioning. The issue arises specifically in Webkit browsers. When using jQuery to retrieve the value, it returns t ...

Having trouble creating a PDF from HTML

Having trouble with generating PDFs using various libraries as I keep encountering the following error: Fatal Error: spawn UNKNOWN The code snippet looks like this: mammoth.convertToHtml({ path: './backend/common/template.docx' } ...

A step-by-step guide on connecting an event listener to the search input of Mapbox GL Geocoder in a Vue application

I've encountered a challenge trying to add an event listener to the Mapbox GL Geocoder search input within a Vue application. It appears to be a straightforward task, but I'm facing difficulties. My objective is to implement a functionality simi ...

Upgrading to Postgres 9.3 for Improved JSON Handling and Date Object Support

Currently working with PostgreSQL 9.3 and exploring options for utilizing TIMESTAMPTZ as authentic JavaScript date objects. Aware of JavaScript lacking a Date literal notation, I considered '{ "key" : new Date(datevalue) }'::JSON as a possibl ...

Angular Alert: [$injector:modulerr] Unable to create the angularCharts module because: Error: [$injector:nomod]

Although this question has been asked multiple times, the standard solutions provided did not resolve my issue. Therefore, I am sharing my code along with the error in hopes that it will be self-explanatory. Error: Uncaught Error: [$injector:modulerr] Fa ...

Developing JavaScript objects with functions using JSON

I am looking to create a specific object with the following structure: var myObj={ "rules": { "email": { "required": true, "email": true, "remote": { "url": "check-email.php", ...

Break up a list into separate paragraphs and style each word using individual CSS

I have a user-generated paragraph that consists of a list of words separated by commas, such as "dog, cat, hamster, turtle." I want to be able to individually assign attributes to each word in the list. Check out this image for reference In the example i ...

Function in head not triggering on OnMouseOver event

My goal is to have specific text display on my page when a user hovers over an image, with the text changing for each image. Below is the code snippet for the header section: <head> <title>Indian Spices Page</title> <link rel="s ...

MySQL and AJAX work together seamlessly in one, yet encounter compatibility issues in the other

I am utilizing AJAX to send a "load call" to a PHP script that includes data to be inserted into a database. The script is structured in the following way: <?php $create_tables = " CREATE TABLE IF NOT EXISTS `user` ( `id` int(11) NOT NULL PRIMARY KEY ...

How do I store the result of an Ajax request as a variable in a different function within a React component?

One of the challenges I'm facing involves making an ajax call that retrieves a list of movies, and then running another function with a separate ajax call to fetch the genre names. Since the first call only provides the genre IDs, I need to match each ...

Releasing an ASP.NET CORE web application with AngularJS on IIS

In the process of developing a new asp.net core web app (using the full .net framework) with AngularJS version 1.5.8, we have encountered an issue. Our app is currently very basic, consisting of just one page displaying student data in a table. When runn ...

Having trouble establishing a basic websocket connection in NodeJS

I am currently following a tutorial on WebSocket protocol development from this link: . Upon visiting localhost:1337/index.html, I encountered the following error: This localhost page cannot be found. No webpage was found for the web address: http://loc ...

Do not directly change a prop - VueJS Datatable

Just starting out on Vue JS and encountered an issue while trying to create a Data Table by passing parent props to child components. An Error Occurred: [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent ...

Difficulty arises when trying to add various text fields to a collection

Lately, I've been making modifications to the Meteor1.3+React Todos app to familiarize myself with the basics, and I must say, it's been a smooth ride so far. However, I have encountered a roadblock. I want to incorporate an additional text field ...

Revise a catalog when an object initiates its own removal

When rendering a card in a parent component for each user post, all data is passed down through props. Although the delete axios call works fine, I find myself having to manually refresh the page for updates to be displayed. Is there a way to have the UI ...

Authenticating with passportjs using a Google Apps email address for verification

I am currently experimenting with using Passport.js along with a Google Apps email ID. I have successfully been able to authenticate using a gmail.com email ID, however, I am facing challenges when attempting to authenticate if the email ID is associated w ...

Conditionally enable or disable button by comparing textbox values within a gridview using C# programming

Hey there! I'm currently diving into the world of JavaScript and C#. Feel free to correct me if you see any mistakes along the way. Check out my gridview code snippet below: <asp:GridView ID="GridView1" CssClass="table table-hover table-bordered" ...

What could explain why the event listener functions properly on the initial call but fails on subsequent calls?

Currently, I am working on a bootstrap carousel where the "Previous" button is hidden on the first slide and the "Next" button is hidden on the last slide. Now, I want to disable the next button on the second slide (and eventually all slides with iframe vi ...