What is the best way to postpone the angular animation until after the model has been bound

I am currently working on a project using AngularJS where I am implementing animations for state transitions. To help with this process, I have been referring to the angular wiki and found this Plunker example:

http://plnkr.co/edit/NsZhDL?p=preview

My issue arises when animating between two <table> elements in different states. The animation (a slide right effect) works correctly, but it triggers before the data is loaded. This results in only the headers sliding in from the right initially, followed by the data being loaded into the <tr> rows. My controller includes an AJAX call to fetch the necessary data, which seems to be executing after the animation. Is there a way to ensure that the data is loaded prior to triggering the animation?

function CategoryList(/*dependencies*/) {
var controller = this;
//setup stuff

//get the data
$http.get('/My/Url', {
    headers: {
        ShowLoading: true
    }
}).success(function (data, status, headers, config) {
    controller.setCategories(data);
});

To address this issue, I attempted using the resolve property within my state object to retrieve the data first and return a promise, but encountered the same problem. Here is my attempt:

.state('myStateName', {
            url: '/myUrl/{id:int}',
            templateUrl: '/mytemplate.html',
            controller: 'ListController',
            controllerAs: 'List',
            resolve: {
                ajaxData: ['$q', '$http', '$stateParams', '$timeout',
                    function ($q, $http, $stateParams, $timeout) {
                        var deferred = $q.defer();
                        // $http returns a promise for the url data
                        $http.get('/Admin/Activities/Category/GetDetail/' + $stateParams.id, {
                            headers: {
                                ShowLoading: false
                            }
                        }).success(function (data) {
                            deferred.resolve(data);
                        }).error(function (data) {
                            deferred.reject();
                        });
                        return deferred.promise;
                    }]
            }

Even though the data retrieval is successful, the animation still precedes it. I had expected the resolve function to execute before instantiating the controller as per the information provided on the angular-ui wiki page: https://github.com/angular-ui/ui-router/wiki#resolve

edit Further research led me to believe that the AJAX request completes before the animation, but the model binding takes place afterwards. This appears to be the current sequence of events:

  1. Click on state transition link
  2. Resolve function retrieves data from server
  3. Fetch destination state's template
  4. Animate the new template into position ([ui-view]-enter yada yada)
  5. Bind the new template to the model.

edit Upon further investigation, it turned out to be a CSS-related issue. The minimum height set on the parent div of the table was causing the tbody content to remain hidden until the animation was completed.

Answer №1

Unfortunately, Plunker is currently experiencing technical difficulties. However, the following code snippet appears to be functional:

var myApp = angular.module('myApp', ["ui.router", "ngAnimate"]);

function resolveData(data) {
  return function ($timeout, $q) {
    var deferred = $q.defer();
    $timeout(function () {
      deferred.resolve(data);
    }, 500);
    return deferred.promise;
  };
}

myApp.config(function ($stateProvider, $urlRouterProvider) {
  $stateProvider
    .state("foo", {
      url: "/foo",
      template: '<h1>{{ info }}</h1>',
      controller: 'FooBarController',
      resolve: {
        info: resolveData('foo')
      }
    })
    .state("bar", {
      url: "/bar",
      template: '<h1>{{ info }}</h1>',
      controller: 'FooBarController',
      resolve: {
        info: resolveData('bar')
      }
    })

  $urlRouterProvider.otherwise("/foo");
});

myApp.controller('FooBarController', function ($scope, info) {
  $scope.info = info;
});

The animations take place once the data has been successfully resolved.

Answer №2

Initially, I was baffled by the resolve function as it didn't seem to work correctly for me.

Below is the code snippet that I've implemented in my current project and it seems to be functioning properly...

var fetchData = ['$q','$http',
  function($q, $http) {
    var deferred = $q.defer();

    // You can initiate your animation code here, but its functionality is unclear.
    $http.get('url')
      .success(function(data) {
        // Once this point is reached, it indicates that you have obtained your data and the resolve will execute, enabling the state transition.
        // If you wish to trigger your animation at this moment, you would include it here
        deferred.resolve(data);
      }
      .error(function(data) {
        deferred.reject();
      }

    return deferred.promise;
  }]

I hope this explanation clears things up for you. Feel free to ask if you need further clarification.

To transfer the resolved data from the resolve function to your target state controller, simply inject it into your controller.

app.controller('someController', ['$scope', 'resolvedData',
  function($scope, resolvedData) {
    $scope.data = resolvedData // This is where your data resides
  }]);

For more information on using resolve in Angular UI Router, refer to the ui.router documentation.

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

The ng-model directive in Angular is effective for handling arrays, however, it may not

The implementation of the ng-model directive seems to be incomplete when dealing with string values in JavaScript. However, by using a list of dictionary objects and looping through them with ng-repeat, this issue is resolved. One reason for this behavior ...

Retrieve the user's IP address from the request rather than Cloudflare's IP address

Cloudflare alters the IP addresses of incoming requests as it acts as a middleman between my website and the Internet, functioning as a proxy. Is there a way to retrieve the original IP address of the request, rather than Cloudflare's IP address? I h ...

Developing Online Shopping Platform with Angular 2

Seeking guidance on selecting the best platform for developing an intermediate to big scale E-commerce system. Currently, we primarily use Codeigniter and sometimes Angular. Interested in exploring the option of using Angular 2 for this project, but still ...

SASS malfunctioning, error messages popping up in command prompt while running gulp serve

As I develop a web app using AngularJS and Gulp, I encounter an issue where the CSS does not seem to work when running 'gulp serve'. Despite attempting to reinstall various components like node_modules, Node.js, and Gulp, the same error persists. ...

Saving the data received from an API in a dedicated service

I am working on storing an API response in a service so that it can be accessed across multiple views. Below is the function I have in my service. It works perfectly when called by my controller, but I want to run this API call only once and then store th ...

Tips for utilizing the dispatchEvent function in JavaScript within an Angular 12 application without passing event data

When trying to fire an event using document.element.dispatchEvent(new CustomEvent('myCustomEvent', 'The string that I try to send when firing the event from my code')), an error was triggered due to a syntax issue. The problem lies in t ...

Is it necessary for services in Domain Driven Design to have knowledge of other services, or should they be aware of multiple repositories

As I work on developing a backend application, my focus is on implementing the Domain Driven Design. However, there's a particular question I have regarding the data structure that requires some clarification. Database Configuration Users Id ( ...

Utilize the RRule library in JavaScript by incorporating the rrule.min.js script

I am having trouble integrating the library https://github.com/jakubroztocil/rrule into my website. Whenever I try to do so, I encounter the error: Uncaught SyntaxError: Unexpected token { I have attempted the following: <!DOCTYPE html> <html ...

Ways to obtain a list of properties for an object

I have a collection of items, each item containing various attributes including a list of related elements: { name : 'Club 01' , id : 1 , form : 45 , points : 0 , tactics : 'neutral' , played : ...

Using Javascript to retrieve the childNode

I have encountered a challenge that I am struggling to overcome. My issue involves utilizing a dynamically generated table with 4 columns: a checkbox, text values, and a hidden input. echo "<tr><td><div class='input-containerh'> ...

How can I automatically fill a vacant value in an array object with a matching object from another array using JavaScript?

Can anyone provide me with some guidance on how to automatically fill in empty table fields based on previous information? I'm struggling to figure it out and would appreciate any ideas. Below is an example of two arrays: one with fruits and the othe ...

Struggling to execute an AJAX request in JavaScript

I am a beginner in .Net development and I am trying to make a call to the client's server. When I test the code using POSTMAN, it works fine. However, when I use the same code/headers in JavaScript, I do not get the desired result. Here is the code I ...

Using parameters in NativeScript-Vue

I'm having trouble passing parameters to another route in Nativescript. Every time I try, it shows up as undefined. I am using the nativescript-vue-navigator. On my current screen, I have this function call: this.$navigator.navigate('/map' ...

How can you include the product price in the cart using the URL on WooCommerce?

After some exploration, I discovered that I can easily add items to my cart using a specific URL: http://yoururl.com/cart/?add-to-cart=ID Although I was able to figure out how to include quantity and attributes in the link, I have not been able to determ ...

Challenges with looping in Jquery animations

I've been working on an animation function that I want to run in a loop. So far, I've managed to get it to work for one iteration, but I'm struggling to figure out how to repeat the loop a specific number of times. Below is the code for my a ...

Utilizing AJAX and Hibernate for a seamless login experience

Creating a login form that is connected to a database has been challenging for me. When a user enters an incorrect username, I want AJAX to respond with "wrong username". My servlet is integrated with Hibernate, allowing me to check usernames against the d ...

Using jQuery and Perl to create a dynamic progress bar that is based on the current state of a "pipeline file" and utilizes AJAX

I'm looking to create a small pipeline that enables users to select a file and run multiple scripts using it as an input. Some of these scripts may take several minutes to complete (time depends on the file's size), so I want to display a progres ...

Using either Javascript or JQuery to update every cell in a particular column of a table

I need to use a button to add "OK" in the Status column of table tblItem, which is initially empty. How can I achieve this using JavaScript or JQuery? The table has an id of tblItem Id Item Price Status 1 A 15 2 B 20 3 C ...

Adjust the background color dynamically as you scroll, given that I am using a linear-gradient

Is it possible to change the color background using JavaScript while scrolling, especially if I have a linear gradient like this: background: linear-gradient(115deg, #42c344 0%,#42c344 40%,#c4efc4 40%,#ffffff 40%,#ffffff 100%); background-attachment: fi ...

Issue with Angular: event.key doesn't register as shft+tab when pressing Shift+Tab key

Our website features a dropdown menu that can be opened and closed by clicking, revealing a list of li items. However, we are currently experiencing an issue with keyboard focus navigation. When the Tab key is pressed, the focus properly moves from one li ...