(Display a loading animation while resolving in Angular-ui-router)

Here is a two part inquiry:

  1. When utilizing the resolve property within $stateProvider.state() to retrieve specific server data before controller loading, is there a method to display a loading animation during this process?

  2. I am facing an issue with child states that also make use of the resolve property. It appears that ui-router insists on finalizing all resolves before initiating any controllers. Is there a way for parent controllers to load once their resolves are resolved, without waiting for all the child resolves? Addressing this may solve the initial problem as well.

Answer №1

UPDATE: I have discovered a simpler solution that has been tested and works smoothly:

Within my primary controller, I have implemented the following code:

$scope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
    if (toState.resolve) {
        $scope.showSpinner();
    }
});
$scope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
    if (toState.resolve) {
        $scope.hideSpinner();
    }
});

This directive displays the spinner when transitioning to a state with unresolved components and hides it once the transition is complete. Although you may need to consider checking up the state hierarchy as well (i.e., displaying the spinner when loading a parent state with resolved elements), this approach suits my needs perfectly.

For reference and as an alternative, here is my previous suggestion:

  1. In your application's controller, monitor the stateChangeStart event to determine if there is a need to display a spinner during resolution (refer to https://github.com/angular-ui/ui-router/wiki/Quick-Reference#wiki-events-1)

    $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
        if (toState.name == 'state.with.resolve') {
            $scope.showSpinner();  //a custom function to show the loading animation
        }
    })
    
  2. Once the controller is activated, hide the spinner accordingly

    .controller('StateWithResolveCtrl', function($scope) {
        $scope.hideSpinner();
    })
    

You may also want to account for any resolve errors by listening for the $stateChangeError event and handling them while concealing the animation.

Distributing the spinner's logic across controllers isn't the most organized approach, but it remains a viable method. I trust this information proves beneficial to you.

Answer №2

Here is my solution that has been working flawlessly for me:

1. Implement the following code in your app.run function

app.run(function($rootScope){

    $rootScope
        .$on('$stateChangeStart', 
            function(event, toState, toParams, fromState, fromParams){ 
                $("#ui-view").html("");
                $(".page-loading").removeClass("hidden");
        });

    $rootScope
        .$on('$stateChangeSuccess',
            function(event, toState, toParams, fromState, fromParams){ 
                $(".page-loading").addClass("hidden");
        });

});

2. Position the loading indicator right above the ui-view section. Ensure that the div containing ui-view has id="ui-view".

<div class="page-loading">Loading...</div>
<div ui-view id="ui-view"></div>

3. Include the following CSS in your stylesheet

.hidden {
  display: none !important;
  visibility: hidden !important;
}

NOTE:

A. The provided code will display the loading indicator in two scenarios 1) during the initial load of the angular app 2) when transitioning between views.

B. To prevent the indicator from showing during the initial app load (before any view is loaded), simply add the hidden class to the loading div as demonstrated below

<div class="page-loading hidden">Loading...</div>

Answer №3

In my experience, the angular-loading-bar has proven to be highly effective for handling lengthy resolves caused by network connectivity.

Answer №4

Consider incorporating dynamic content into the div that will be populated by ui-router upon resolution of the properties.

In your index.html

<div ui-view class="container">
    Loading....
</div>

Users will initially see "Loading..." while the properties are being resolved. Once everything is set, ui-router will replace the loading message with the actual content of your application.

Answer №5

Whenever there are pending requests with $http, I display an animated gif.

Within my base page template, I have a navbar and a corresponding controller. The excerpt from the controller is as follows:

controllers.controller('NavbarCtrl', ['$scope', '$http',
    function ($scope, $http) {
        $scope.hasPendingRequests = function () {
            return $http.pendingRequests.length > 0;
        };
    }]);

The relevant code in the HTML document looks like this:

<span class="navbar-spinner" ng-show="hasPendingRequests()">
    <img src="/static/img/spinner.gif">
</span>

I trust this information proves to be beneficial!

Answer №6

My concept involves traversing the state graph between changing states during the $stateChangeStart event and identifying all views that are affected. Each ui-view directive then monitors whether its corresponding view is part of the transition and applies a 'ui-resolving' class to its element.

In the demonstration provided in this plunker, there are two root states: first and second. The state second has two child states, second.sub1 and second.sub2. Additionally, the state second.sub2 targets the footer view associated with its parent state.

Answer №7

This code snippet is used as a loader for the entire application when navigating between different states or pages. It should be placed in the app.js file.

.run(
    ['$rootScope',
        function($rootScope) {
            $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
                $rootScope.preloader = true;
            })
            $rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
                $rootScope.preloader = false;
            })
        }
    ])

In html:

<div ng-show="preloader">Loading...</div>

Answer №8

Deprecated methods like $stateChangeStart have now been replaced by Transition Hooks. Here is an updated version provided by Stefan Henze:

$transitions.onStart({}, function(transition) {
  if (transition.to().resolve) {
    $scope.showSpinner();
  }
});

$transitions.onSuccess({}, function(transition) {
  if (transition.to().resolve) {
    $scope.hideSpinner();
  }
});

You can implement this in your parent controller. Make sure to inject $transitions -

.controller('parentController',['$transitions',function($transitions){...}]);

Keep in mind that even an empty object as a resolve will be considered true, so avoid leaving blank placeholders in the state declaration.

Answer №9

I find it beneficial to utilize a directive for handling any loading tasks, as it helps maintain the cleanliness of my codebase.

angular.module('$loadingUtilities', [])
.directive('loaderManager',['$timeout','$rootScope', function($timeout, $rootScope) {
    return {
      restrict: 'A',
      template: '<div id="oneloader" class="hiddenload">loading...</div>',
      replace: true,
      compile: function (scope, element, attrs) {
        $timeout(function(){
          $rootScope
              .$on('$stateChangeStart',
                  function(event, toState, toParams, fromState, fromParams){
                      $("#oneloader").removeClass("hiddenload");
              });

          $rootScope
              .$on('$stateChangeSuccess',
                  function(event, toState, toParams, fromState, fromParams){
                      //introduce a slight delay
                      $timeout(function(){
                        $("#oneloader").addClass("hiddenload");
                      },500)
              });
        }, 0);
      }
    }
  }]);

Answer №10

Implementing a view with resolve in the router has greatly improved my application's performance. Give it a try!

//update index.html file 
<ion-nav-view>
    <div ng-show="loader" class="loadingSvg">
        <div class="svgImage"></div>
    </div>
</ion-nav-view>

// styles.css file

.loadingSvg {
    height: 100%;
    background-color: rgba(0, 0, 0, 0.1);
    position: absolute;
    z-index: 99;
    left: 0;
    right: 0;
}

.svgImage {
    background: url(../img/default.svg) no-repeat;
    position: relative;
    z-index: 99;
    height: 65px;
    width: 65px;
    background-size: 56px;
    top: 50%;
    margin: 0 auto;
}

// update app.js

 .run(function($ionicPush, $rootScope, $ionicPlatform) {




        $rootScope.$on('$stateChangeStart',
            function(event, toState, toParams, fromState, fromParams) {
                $rootScope.loader = true;
            });

        $rootScope.$on('$stateChangeSuccess',
            function(event, toState, toParams, fromState, fromParams) {
                $rootScope.loader = false;
            });

});

Answer №11

If you are utilizing ngRoute, awaiting the completion of resolve before transitioning to the next view, and integrating angular-bootstrap-ui for UI components, you can implement the following solution:

app.config([
  "$routeProvider", "$locationProvider", function($routeProvider, $locationProvider) {
    return $routeProvider.when("/seasons/:seasonId", {
      templateUrl: "season-manage.html",
      controller: "SeasonManageController",
      resolve: {
        season: [
          "$route", "$q", "$http", "$modal", function($route, $q, $http, $modal) {
            var modal, promise, seasonId;
            modal = $modal.open({
              backdrop: "static",
              template: "<div>\n  <div class=\"modal-header\">\n    <h3 class=\"modal-title\">\n      Loading...\n    </h3>\n  </div>\n  <div class=\"modal-body\">\n    <progressbar\n      class=\"progress-striped active\"\n      value=\"'100'\">\n    </progressbar>\n  </div>\n</div>",
              keyboard: false,
              size: "lg"
            });
            promise = $q.defer();
            seasonId = $route.current.params.seasonId;
            $http.get("/api/match/seasons/" + seasonId).success(function(data) {
              modal.close();
              promise.resolve(data);
            }).error(function(data) {
              modal.close();
              promise.reject(data);
            });

            return promise.promise;
          }
        ]
      }
    });
  }
]);

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

Adjust the input values based on the child elements within the main container

Here is a series of DIVs with unique IDs: <div id="2988"> <div class="site">YaHoot.com</div> <div class="logo">/images/yahootLogo.jpg</div> //[and so on] <input type="button" value="YaHoot" onclick="javascript: ...

What is the right way to display accurate value with JSON.parse()?

I'm struggling to correctly parse some JSON code. Instead of just displaying messages, I am getting extra information such as Object and Array. How can I modify the code to only show the messages I need? var txt = ""; var json_string = JSON.stringify ...

JavaScript does not allow executing methods on imported arrays and maps

In my coding project, I created a map named queue in FILE 1. This map was fully built up with values and keys within FILE 1, and then exported to FILE 2 using module.exports.queue = (queue). Here is the code from FILE 1: let queue = new.Map() let key = &q ...

Can I substitute custom tags for the traditional <p> tag?

My HTML with CSS has an issue where a custom HTML tag is not displaying the text while my CSS picks up another tag. Interestingly, replacing <title>Layout Controls</title> with <p>Layout Controls</p> resolves the problem and shows t ...

Efficient Techniques for Concealing and Revealing Navigation Menus using HTML, CSS, and JavaScript

I need help making the menu icon toggle the navigate menu between showing and hiding when clicked on the top right corner of the screen. For better understanding, here is an accompanying image: https://i.stack.imgur.com/oy6d9.png However, the current co ...

What is the best way to navigate and map through an array of objects, especially when encountering an empty object?

I am currently in the process of developing a bootleg version of Amazon with a focus on creating the Questions & Answers component. The issue I have encountered is that in my dummyData, there are instances where a product may not have any questions, lead ...

Unable to communicate between react components

I am currently working on a project using React JS (jsfiddle). The issue I am facing is that the textbox does not update with the true/false value of the checkbox when it is checked. Can anyone provide insight into why this might be happening? var Custo ...

What is the best way to arrange an array of objects by their ID in a React application?

I am currently in the process of developing my own social media application. At this point, I have a feature that allows users to post content or text on the platform. I have also set up temporary data in the form of an array of objects, which is currently ...

How can we access a value within a deeply nested JSON object in Node.js when the key values in between are not

In the nested configuration object provided below, I am seeking to retrieve the value associated with key1, which in this case is "value1". It's important to note that while key1 remains static, the values for randomGeneratedNumber and randomGenerated ...

Tips for shutting down an HTML webpage with the help of JavaScript

Recently, I've been working on a project to implement a feature that automatically closes the website when an incorrect password is entered. However, I am fairly new to JavaScript and still in the early stages of learning. Below is the code snippet I ...

Detaching jQuery event listeners

Suppose I have two event handlers of the same type attached to the same object. The following example shows the mousemove event being attached to the window object. $('body').on('mousedown', '#uiScrollbar', function(e) { v ...

AngularJS: How can I eliminate the #! from a URL?

Looking for guidance on how to remove #! from the URL in AngularJS using ng-route. Can anyone provide a step-by-step process on removing #!? Below is the code snippet: index.html <head> <script src="https://ajax.googleapis.com/ajax/libs/ang ...

Using jQuery effects on your PHP message to give it an interactive touch - here's how!

For some time now, my website has had a straightforward PHP message system that worked well, storing data into MySQL with each message having a unique ID. Recently, out of the blue, I decided to enhance the system by adding jQuery effects for sending and d ...

Upon refreshing the page, next.js 13's useSession() function fails to fetch session information

Currently, I am working on replicating an ecommerce site using nextjs 13. On the order page, I am utilizing useSession from next-auth/react to check if a user is signed in or not. Everything works fine when I navigate to the page through a link, but if I r ...

The issue with the demo variable not functioning properly within the ngOnChanges method of the child component

I am facing an issue in child.component.ts where I am using the demo variable with input(), but it is not showing up in the developer console. app.html <input type="text" placeholder="text" #val> <br> <button (click)="submitValue(val)"> ...

What strategies can I use to prevent the need to create new instances of my service and repository for every

Currently, I am delving into the world of JavaScript using the Express.js Framework. My current learning project involves creating a simple restaurant application to grasp the ins and outs of CRUD operations related to ingredients. I have meticulously craf ...

Importing data with D3

I'm currently diving into D3 and facing an issue with some code written in an older version of the library. The data loading process has changed in version 5.7.0, and I'm struggling to make it work for this specific example. Loading data with jus ...

Fetching from the same origin results in a null comparison issue due to HTTP CORS restrictions

Encountering an issue where a simple same-origin fetch("fetch.xml") call fails, resulting in a console error message Access to fetch at 'http://127.0.0.1:8000/fetch.xml' from origin 'null' has been blocked by CORS policy: Th ...

Resolving issues with a countdown timer coming to a halt

After creating a countdown timer to show 45 seconds on the screen, I attempted to control it using two buttons with JavaScript's onclick function. One button is meant to start the timer while the other stops it. While I was successful in starting the ...

Uneven rotation of objects within the browser

I am currently working on visualizing objects in a web browser. The goal is to display these objects rotating around one axis at a time (either X, Y, or Z) or allow the user to interactively rotate them using their mouse. However, I have encountered severa ...