Question

I am building an Angular app using state hierarchy provided by the angular-ui/ui-router library.

I have a request that takes many minutes to complete, so the goal is to POST to a request resource and then poll the server to determine when the request completes. The app is quite large and different areas of the site are organized into different decoupled modules, but the header is managed by a common root state.

In order to message the completion event to the user without disturbing their browsing session, I would like to:

  • Add a "loading" spinner to the header of the app when the request is made
  • Allow the user to continue browsing the site but retain the "loading" spinner
  • Replace the spinner with a "check" icon once the polling determines that the request has been completed.

How can i encapsulate this process and allow it to continue running through multiple state transitions?

Was it helpful?

Solution 2

I'm not entirely sure how ui-router works, but if it's anything like $routeProvider (or you're using $routeProvider as well), you can assign a controller to the "header of the app" and let that controller do the work.

Below is a basic example of how it would work. _handleLoad simulates polling the server, and when it's all done, you can change the header easily (or the rest of your site using $broadcast). The $routeProvider let's the user browse the site while the HeaderCtrl continues executing on the page.

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

app.controller('HeaderCtrl', function ($scope, $timeout) {
  var _i = 0,
      _handleLoad = function () {
        console.log('checking..');
        // TODO check the server here, fire the $timeout in the callback if the process isn't complete
        if (_i == 3) {
          $scope.loading = false;
          _i = 0;
          $scope.headerText = 'we have loaded something';
          console.log('all done');
          return;
        }
        _i += 1;

        $timeout(_handleLoad, 1000);
      };

  $scope.headerText = 'click here to load something';
  $scope.loading = false;

  $scope.load = function () {
    $scope.loading = true;
    _handleLoad();
  }
});

OTHER TIPS

You can create an abstract state that child states will inherit from. Add a service that polls for the status of the long running request. All of the children states will have access to the abstract controller via the $scope.$parent property.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top