Parent scope receives directive updates with a slight delay

I recently made a transition of my simple paging feature from the controller to a directive, but encountered a peculiar issue. Whenever I update the parent scope from within the directive, the changes only reflect on the next alteration. For instance, if the ng-options are [10,20,30] and I change it to 10, nothing happens. Then, when I switch it to 20, it reverts back to the previous value of 10, and so on.

Despite trying to use $scope.$apply, the updates still get delayed. I seem to be missing something here. It appears to be related to digest update and $scope.$apply, but I'm struggling to determine where exactly to apply it. Everything I attempt just doesn't seem to work.

The relevant sections in the controller:

vm.pages = 0;
vm.articles = [];

vm.load = { page: { batch: 10, current: 1 }
          , sort: { _id: -1 }
          , filter: {}
          };

vm.getArticles = function() {
  articleS.list(vm.load, function (data){
    vm.pages = data.pages;
    vm.articles = data.articles;
  });
}

The directive:

.directive("paging", function() {

  var scope = { update: '&', current: '=', pages: '=', batch: '=' };

  function link(s, e, a) {
    s.options = [10,20,50,100];

    s.toPage = function(p) {

      switch(p) {
        case "last":
          if (s.current != s.pages) {
            s.current = s.pages;
            s.update();
          }
          break;
        case "next":
          if (s.current < s.pages) {
            s.current ++;
            s.update();
          }
          break;
        case "prev":
          if (s.current > 1) {
            s.current --;
            s.update();
          }
          break;
        default:
          s.current = 1;
          s.update();
      }

    }
  }

  return {
    replace: true,
    scope: scope,
    templateUrl: 'paging.tpl',
    link: link
  }
});

The directive template:

<section class='pages'>
    <select
            ng-model="batch"
            ng-change="toPage('first')"
            ng-options="value for value in options">
    </select>
    <div>
      <button ng-click="toPage('first')"> 1 </button>
      <button ng-click="toPage('prev')"> << </button>
      <div>{{current}}</div>
      <button ng-click="toPage('next')"> >> </button>
      <button ng-click="toPage('last')"> {{pages}} </button>
    </div>
  </section>

Directive call:

      <paging
        update="vm.getArticles()"
        current="vm.load.page.current"
        batch="vm.load.page.batch"
        pages="vm.pages">
      </paging>

Answer №1

After some investigation, I have come to a conclusion. It seems that using $apply on an isolated scope variable bound to its parent with '=' might result in an 'already in progress' error. From what I've noticed through trial and error, it appears that '=' triggers the $digest process.

The issue I encountered was due to the s.update() function being executed before the next digest cycle. This meant that the local scope variables did not have enough time to copy to the parent scope, resulting in me only seeing the update during the next operation or digest cycle, hence always observing the previous change. By using

setTimeout(function(){ s.update() }, 2000)
, I was able to confirm this theory. Delaying the execution by a few seconds allowed me to see the update with the correct changes. However, relying on such delays is not a viable solution as it simply slows down the application unnecessarily. Fortunately, I later discovered Angular's $timeout(function() {}). This function does not actually introduce any delay (as it defaults to 0), but ensures that the callback runs on the next digest cycle, facilitating the updating of local scope variables to the parent.

if (s.current < s.pages) {
  s.current ++;
  $timeout(function() {
    s.update();
  });
}

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

JavaScript: selecting multiple elements with identical attributes

I'm struggling to target all a tags with the 'data-caption' attribute. I attempted to do this by: first selecting all the a tags let links = document.querySelectorAll('a'); and then trying to access their attributes links.get ...

How can I assign several Objects to a single array?

My goal is to save several objects into an array. Specifically, I have five objects named obj1, obj2, obj3, obj4, and obj5. ...

Do you think my plan to develop an HTML parser from the ground up will be successful?

My goal is to enhance my skills by building an HTML parser. The basic idea I have in mind includes: Defining the tokenization using regex. Taking a string of HTML as input. Iterating through the HTML string. Storing details about each token, such as cont ...

Structuring files with AJAX, PHP, Javascript, and HTML

Explaining my dilemma in detail might be a bit abstract, but I'll try to do my best. In one of my PHP files, I have HTML code that includes text boxes and a submit button. This file serves as the main page and is named mainHTML.php The text boxes ar ...

Using Selenium to interact with a link's href attribute through JavaScript

New to Java and Selenium, I'm facing difficulties when trying to click on a link with JavaScript in href attribute. Here's the snippet from the page source: href="javascript:navigateToDiffTab('https://site_url/medications','Are y ...

Instructions for retrieving data from a weather API using JavaScript

Hello amazing Stackoverflow community! I need your help to figure out how to extract data from a weather REST API using JavaScript. I'm struggling to fetch the weather condition and date/time information from this API. { info: { _postman_i ...

Verify if a username is available using jQuery

When trying to register, I use this function to check the availability of a username. If the username already exists, the submit button is disabled. The check is done using a php script that queries the database for existing usernames. Everything works per ...

``There seems to be an issue with setting the input value attribute using jQuery's .html

I've been trying to update the value attribute in the input element within my HTML code, but so far, I haven't had any luck with it. HTML: <div class='photo-info'> Photo Name : <span class='photo-name'><?p ...

Exploring arrays and objects in handlebars: A closer look at iteration

Database Schema Setup var ItemSchema = mongoose.Schema({ username: { type: String, index: true }, path: { type: String }, originalname: { type: String } }); var Item = module.exports = mongoose.model('Item',ItemSchema, 'itemi ...

The ability to retrieve variables within a certain scope from a function that is declared externally

Is there a method to access and print the value of a closure variable, temp, from a function defined outside the closure but referenced within it without passing temp as an argument to the function? var funcA, funcB; funcA = function () { console.log( ...

Experiencing an unexpected abundance of console logs when implementing React Hooks

I am attempting to retrieve data from an API. The desired result is being obtained, but when I attempt to log it to the console, it logs 4 times. Within my app.js, I am utilizing the fetchData function: import React, {useEffect, useState} from 'rea ...

What is the method for rearranging the module menu item order in mean.io?

I integrated each module of my application into the menu of mean.io by adding them to the app.js file in this manner: Theme.menus.add({ title: 'theme example page', link: 'theme example page', roles: ['authenticated&ap ...

Displaying an RSS feed inside a designated div element

Seeking assistance from all you wonderful individuals for what seems to be a simple problem. Here is the HTML code I am working with: <div id="rssfeed"></div> Along with JavaScript that includes the FeedEK plugin $(document).ready(function ...

Adjustable height and maximum height with overflow functionality

Currently, I am in the process of developing a task manager for my application and facing an obstacle when trying to calculate the height of a widget. My goal is to determine the maximum height (assuming a minimum height is already set) by subtracting a ce ...

Click a button to load a different view in CodeIgniter

How can I show another view of Controller using Ajax/Javascript when clicking a button? I attempted something, but it's not working as expected. Javascript: <script> $(document).ready(function(){ $("#details").click(function(){ $( ...

PHP Timer for Keeping Track of Time

Is it feasible to develop a timer using PHP that triggers an action after 60 seconds? I am looking for a countdown effect where the timer starts at 60 and decreases to 0. Ideally, I would like to refresh the corresponding div element to simulate the countd ...

Using Protractor to extract text from multiple paragraphs

How do I retrieve the values of all paragraphs (p) at once? Below is an example of how my inspect view appears: "Testing sample one." "Testing sample two." And here is a snippet of my code to extract the value of id 'run': browser.findElement ...

Tips for preventing the sidebar from extending beyond the footer

I am facing an issue with my sidebar that follows as I scroll. How can I make it stop following when it reaches the footer? Here's what I have attempted so far: $(function() { var floatPosition = parseInt($("#left_menu").css('top')); ...

Using Node.js to handle reading files and dealing with undefined or null values

The get method is responsible for receiving a userid with an initial total number of points defined in the stcok.json file, along with various transactions stored in another file. Below are some sample entries from the stock JSON: [ { "user" ...

Transitioning React Hover Navbar Design

I'm currently revamping a click-to-open navbar into a hover bar for a new project. I have successfully implemented the onMouseEnter and onMouseLeave functions, allowing the navbar to open and close on mouse hover. However, I am facing an issue with ad ...