What is the reason for the ng-style function being called twice?

In my angular application, I have defined a module called 'ngStyleApp' with a controller named 'testCtrl' that contains a list of numbers and a function to return styles based on the index.

angular.module('ngStyleApp', [])

.controller('testCtrl', function($scope) {
   $scope.list = [1,2,3];
   $scope.getStyles = function(index) {
       console.log('getting styles for index ' + index);
       return {
           color: 'red'
       };
   };
});

The corresponding HTML markup displays a list using ng-repeat and applies styles using ng-style:

<div ng-app="ngStyleApp">
    <ul ng-controller="testCtrl">
        <li ng-repeat="value in list" ng-style="getStyles($index)">
            {{value}}
        </li>
    </ul>
</div>

Even though the expected output is three red list items, the console logs show that the styles function is being called multiple times:

getting styles for index 0
getting styles for index 1
getting styles for index 2
getting styles for index 0
getting styles for index 1
getting styles for index 2

What could be causing this duplication?

Answer №1

During the Angular $digest cycle, the ngStyle attribute is evaluated multiple times to determine its value and check for any changes. This process continues until the value stabilizes, leading to potentially multiple checks.

For a visual representation, take a look at this image:

If you're looking for further explanation, check out this insightful blog post: angular digest blog

Alternatively, consider this explanation from StackOverflow:

During the $digest cycle, Angular evaluates watched functions and checks for changes in variables used by other watched functions. This process, known as dirty processing, continues until no changes are detected. It is not uncommon to see multiple calls to watched functions per digest cycle, with up to 10 loops before Angular reports an error due to inability to stabilize.

(Source: here)

Answer №2

This section includes the implementation of the ngStyle directive:

var ngStyleDirective = ngDirective(function(myScope, myElement, myAttr) {
  myScope.$watch(myAttr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {
    if (oldStyles && (newStyles !== oldStyles)) {
      forEach(oldStyles, function(key, value) { myElement.css(key, '');});
    }
    if (newStyles) myElement.css(newStyles);
  }, true);
});

It's worth noting that the scope.$watch function is used with attr.ngStyle, causing the action to trigger twice.

On the other hand, if a similar operation is attempted with ngInit, the function is only executed once. Take a look at the code snippet for the ngInit directive:

var ngInitDirective = ngDirective({
  priority: 450,
  compile: function() {
    return {
      pre: function(myScope, myElement, myAttrs) {
        myScope.$eval(myAttrs.ngInit);
      }
    };
  }
});

An interesting difference is that there is no watch utilized within this directive.

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

A method for merging the values of three text fields and submitting them to a hidden text field

<label class="textRight label95 select205">Cost Center: </label> <input type="hidden" name="label_0" value="Cost Center" /> <input type="text" name="value_0" class="input64 inputTxtGray" value="" maxlength="10" /> <input type=" ...

Require Google Chrome to show a blank page upon refresh

After reloading the page in either IE/Edge or Chrome/Firefox, I noticed a significant difference. IE/Edge clears the page and displays a white page, while Chrome/Firefox does not. I'm wondering if there is a way to use JavaScript to instruct Chrome/F ...

Locate a specific element within an array and retrieve its corresponding index

Need help updating a boolean property for all objects in an array with the same user ID. I've outlined my MVC framework below in a concise manner. Model: var posts = [{id:1, user_id:1, is_following:true}, {id:2, user_id:1, is_cool:true}, ...

Is there a way to set a fixed value for properties in Three.js?

I am on the hunt for the equivalent in Three.js to vertexAttrib. My goal is to assign a fixed value to my shader attribute. ...

When you zoom in, the HTML elements tend to shift out of place

Spent the entire day yesterday attempting to make my page responsive while Zooming In, but I just can't seem to get it right. Even after adding height and weight, elements still get mixed up when zooming in on the page. I've scoured countless w ...

AngularJS throwing obscure error message when trying to access object

Whenever I try to access the object below, it results in an undefined error: { "code": 422, "message": { "address_info.email": [ "The address info.email field is required." ] }, "debug": null } In my code, when ...

How to pass arguments to the `find` method in MongoDB collections

I've been attempting to pass arguments from a function to the MongoDB collection find method. Here's what I have so far: async find() { try { return await db.collection('users').find.apply(null, arguments); } catch(err) { c ...

Why does the React input value keep its value when the modal is re-rendered, despite the state being updated correctly?

Take a look at this sandbox link for the code snippet: Sandbox Showcased below is a table structure: https://i.sstatic.net/3F3Mc.png By clicking on the 'edit' button, a modal window opens up as shown below allowing you to edit input fields (onC ...

AngularJS routing fails to function when viewing past actions

Currently, I am working on coding an Angular application and have completed setting up my app routing as shown below: AdminDashboard.config(['$routeProvider','$locationProvider',function($routeProvider, $locationProvider){ $rou ...

I am currently attempting to create a JavaScript function that searches for the <td> elements within an HTML table. However, the function fails to work properly when there are <th></th> tags included

UPDATE: Scratch that, I managed to solve my issue by creating a separate table for the header to contain all of my <th> tags I am working with an HTML table and I would like to add a search bar to filter through the content since it is quite large. ...

The ReactCSSTransitionGroup does not insert any additional classes

I have been attempting to incorporate animation into each list item within a list of articles that I am loading through an ajax request. Despite my efforts, the ReactCSSTransitionGroup element does not seem to be functioning as expected on the targeted ite ...

Show information according to the user's input

I am working on a page layout that includes two columns: Side and Middle. Within the side column, there is a form containing a date input and a button labeled "View Summary Report." Upon selecting a date and clicking the button, the goal is to retrieve d ...

Do we need to use aria-labelledby if we already have label and input associated with "for" and "id"?

Here is the HTML structure for the Text Field component from Adobe Spectrum: The <label> element has a for attribute and the <input> has an id which allows screen readers to read out the label when the input is focused. So, why is aria-label ...

Understanding Variable Scope in JavaScript: How Variables are Accessed in Different Functions

I've been experimenting with a script that utilizes jQuery's get function to transfer data to another page and display the returned information as an alert on the current page. My goal is to send both the search field value from an input form (wh ...

Move a <div> using a handle (without using JQuery)

I devised a plan to create a moveable div with a handle and came up with this code snippet: var mydragg = function() { return { move: function(divid, xpos, ypos) { divid.style.left = xpos + 'px'; divid.style.top = ypos + &apo ...

The onblur function is not being triggered

Recently, I encountered an issue while trying to invoke a JavaScript function onblur of a field. The main problems I faced were: 1) The popup inside the function call was triggered automatically during page load. 2) When attempting to access the functio ...

How to effectively inject moment.js dependency into AngularJS?

In my app.js file, I've defined my app module like this: var myApp = angular.module('myApp', ['angularMoment']); Next, in my controller, I'm trying to use the moment() function: myApp.controller('myComtroller', [& ...

Enhance jQuery for a dynamic navigation dropdown with multiple sub-menus

Looking for help with a jQuery script as I am a beginner in using jQuery. jQuery(document).ready(function ($) { $(".sub-menu").hide(); $(".current_page_item .sub-menu").slideDown(200);; $("li.menu-item").click(function () { if ($('.sub-menu&apos ...

Filtering data in a table using Vue.js on the client side

I am facing an issue with filtering a table containing student details retrieved from a database using v-for. I am attempting to filter the table based on a specific field value. To begin with, I have three input fields located above the table, each bound ...

Resolved plugin issue through CSS adjustments

Take a look at this template 1) After referring to the above template, I developed a fixed plugin using JavaScript. 2) Clicking the icon will trigger the opening of a card. 3) Within the card, I designed a form using mdb bootstrap. Everything seems to ...