Is there a way to make $animate.removeClass function within a directive without needing to use $eval

I have developed a custom directive that smoothly fades out and fades in the content whenever there is a change in the model.

app.controller('myCtrl', function($scope, $interval) {
  $scope.number = 0;
  $interval(function() {
    $scope.number++;
  }, 1000);
});

app.directive('fadeOnChange', function($timeout, $animate) {
  return {
    restrict: 'E',

    //Displaying the value with transition effects
    template: '{{theFadedValue.nv}}',

    link: function(scope, elem, attr) {
      //Watching the specified variable on scope
      var vtw = attr.valueToWatch;

      //Adding animation class for transitions
      $animate.addClass(elem, 'anim');

      //Watching the value changes
      scope.$watch(vtw, function(nv) {

        //Fade out effect
        var promise = $animate.addClass(elem, 'fade-it-out');

        //After fade out, updating the new value
        promise.then(function() {

          scope.$evalAsync(function() {
             scope.theFadedValue = {"nv": nv};
            //Fading it back in
            $animate.removeClass(elem, 'fade-it-out');
          });
        });
      })
    }
  };
});

Here is how the view looks like:

<div ng-controller="myCtrl">
  <h1><fade-on-change value-to-watch="number"></fade-on-change></h1>
</div>

The functionality works flawlessly, but I am curious as to why I need to use $apply, $digest, $timeout or $evalAsync to encapsulate my call to $animate.removeClass in order for it to work properly. Without them, the class does not get removed as expected, leading to some confusion.

I have read about these methods and their distinctions, yet the necessity of using one of them specifically in this scenario perplexes me.

Link to demo

Answer №1

Typically, async methods do not directly trigger the $digest cycle in AngularJS. However, there is an exceptional case with the $http service where it internally wraps inside $scope.$apply().

In your situation, you are waiting for a promise to complete which is asynchronous. To ensure that the scope variables get updated, you can use either $timeout(function(){ }) or $evalAsync. These Angular services wrap inside $scope.$apply(), which then triggers the digest cycle updating all scope variables.

$evalAsync runs after the DOM has been manipulated by Angular, but before the browser renders.

Click here for more information on when to use $scope.$apply().

I hope this explanation clarifies any doubts you may have. Thank you.

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

Oops! An error has occurred with the module in angular1

I recently integrated ui-router into my Angular 1 application and set up the route state. However, I encountered an error when trying to access the page mentioned in the title of this post. Below is the code snippet for reference. Can anyone point out wher ...

Guide on how to use a tooltip for a switch component in Material-UI with React

I am attempting to incorporate a tooltip around an interactive MUI switch button that changes dynamically with user input. Here is the code snippet I have implemented so far: import * as React from 'react'; import { styled } from '@mui/mater ...

Adding text after a div in React-JS using Bootstrap: A quick guide

Just starting out with website development and I have a question. As I practice making this website, I am struggling to figure out how to add the text "To know more about us click here" below the 'Get started' button. I tried adding a simple < ...

JavaScript obtain scroll position of a child element

I have a setup that looks something like the following: <div> <div id="scrollID" style="height:100px;"> content here </div> </div> <script> document.getElementById("myDIV").addEventListener("touchstart", m ...

Good day extract a collection of articles

I am trying to parse out the date and full URL from articles. const cheerio = require('cheerio'); const request = require('request'); const resolveRelative = require('resolve-relative-url'); request('https://www.m ...

Implementing conditional dropdown menus with CodeIgniter

Explore the District Master Table: https://i.sstatic.net/n6kvV.jpg Dive into the District table: https://i.sstatic.net/uQqcW.jpg District Master District I need assistance with a form page that includes a Category dropdown. The district table stores d ...

Trigger a function from a Bootstrap modal

Here is a preview of my HTML code : <form action="form2_action.php" method="post"> <table> <tr> <td>First Name </td> <td>:</td> <td><input type="text" id="f ...

Include a Vue component within another Vue component in a Laravel application using VueJs

I've recently integrated Vue.js into my Laravel project and encountered an issue when trying to call a component within another component. After running the command npm run dev, I received a webpack error. Here is the code snippet from my parent comp ...

Steps for adding a forked version of a library in package.json

Recently, I came across a React JS library called React Pacomo. Since the original version of this library is no longer being maintained, I decided to use my own forked version for my project. However, I am facing issues with compiling or building the libr ...

Generating a default template for an Angular ag-Grid cell with a custom field name - how to do it?

I am currently working with ag-grid and have specific templates for many columns. However, some of the data I am inputting into the table are just plain text. I want to enhance the default case: <ng-template #defaultRecord let-record> ADDITIONAL E ...

Utilizing TypeScript interfaces to infer React child props

How can I infer the props of the first child element and enforce them in TypeScript? I've been struggling with generics and haven't been able to get the type inference to work. I want to securely pass component props from a wrapper to the first ...

Viewing a PDF within a MUI tooltip

Currently, I am facing an issue where I am attempting to show a preview of a PDF file inside a Material-UI (MUI) Tooltip when a user hovers over a MUI ListItem. While I have successfully displayed previews of PNG and JPG files using Next.js' Image com ...

How do I customize the time range for the weekly schedule on fullcalendar to show only from 9:00 AM to 6:00 PM instead of the default 0:00 to

Calendar by AngularUI and FullCalendar by Arshaw I am currently utilizing the ui-calendar for my project. However, I am facing an issue where the weekly times are showing all 24 hours of the day. Is there a way to adjust the settings so that it only displ ...

Modifying paragraph content with JavaScript based on selected radio button values and troubleshooting the onclick event not triggering

I am working on implementing a language selection feature on my website where users can choose between English and Spanish. The idea is to have two radio buttons, one for each language, and a button. When the button is clicked, the text of the paragraphs s ...

What is the reason that the <script> tag cannot be directly inserted into the .html() method?

As I continue to learn front-end development, I've created my own version of JS Bin. When the 'run' button is clicked, a statement is executed to showcase the HTML, CSS, and JavaScript in an iframe (the output window): ("iframe").contents() ...

Error: Identical div IDs detected

<div id="tagTree1" class="span-6 border" style='width:280px;height:400px;overflow:auto;float:left;margin:10px; '> <a class="tabheader" style="font-size:large">Data Type</a><br /> <div class="pane">Refine sea ...

What is the best way to implement a new search input for my datatable while also enabling the searchHighlight feature?

I'm attempting to implement a search bar for my datatables. I need to hide the default search engine that comes with datatables, so I added a script that I found in a forum. However, when I try to run it in my code, it doesn't work and displays a ...

The issue arises when the cache code in jQuery Ajax interferes with the callback function, causing it to

I encountered an issue with my code related to cache. The problem arises when there is an ajax call with a callback in the success function. var localCache = { /** * timeout for cache in millis * @type {number} */ timeout: 30000, ...

Ways to activate JavaScript on a completely dynamic AJAX ASP.NET website

Encountering a dilemma: I have developed a fully dynamic site with only one update panel on the startpage. All content is generated dynamically through code behind, with different pages as web user controls. The issue arises when attempting to open two d ...

When Angular is loaded, it appears to modify the browser's stylesheet

After adding the angularjs JavaScript file to my app, I noticed that some text was appearing smaller on the page and causing issues with padding. Has anyone else encountered this problem? Do you know what changes angular is making to the browser's sty ...