angular-ui / ui-router

The de-facto solution to flexible routing with nested views in AngularJS
http://ui-router.github.io/
MIT License
13.56k stars 3.01k forks source link

Child controller trigger before parent completes all resolve in UI-Router #3745

Closed GhazanfarKhan closed 5 years ago

GhazanfarKhan commented 5 years ago

I have a parent route called engine. Here I am validating token, loading all db stuff, checking boolean values and navigating to different routes based on data. This whole process works fine if I navigate from parent to child but when I refresh child route its controller init function trigger first before parent resolve got finished.

Here is my sample code

angular.module('demoApp', ['ui.router'])
.config(routes);

function routes($urlRouterProvider, $stateProvider) {
  $urlRouterProvider.otherwise('/engine/121212');
  $stateProvider
    .state('engine', {
      url: 'engine/:token',
      template: '<div ui-view></div>',
      resolve: {
        PreValidateTokenParams: function($stateParams, $q, $timeout, $state) {
          debugger;
          console.log('in validate token');
          $timeout(function() {
            deferred.resolve(true);
          }, 1000);
          return deferred.promise;
        }
      },
      ResponseData: function(PreValidateTokenParams, $q, $state) {
        var deferred = $q.defer();
        $timeout(function() {
          deferred.resolve(true);
          $state.go('engine.survey');
        }, 100);

        return deferred.promise;
      }

    })
    .state('engine.survey', {
      url: '/survey',
      parent: 'engine',
      controller: function() {
        function init() {
          console.log('init survey');
          //Need to update status in database
        }
        init();
      },
      template: '<h1>Survey</h1>'
    })
}

I am tracking different page rendering events in database. This breaks the event login if I refresh the page in survey route then survey rendered status got executed first. How do I handle this scenario.

shirazz commented 5 years ago
$stateProvider.state('store', {
  abstract: true,
  views: {
    content: {
      template: "<div ui-view='content'></div>"
    }
  },
  resolve: {
    _auth: function (AuthService) {
      return AuthService.authenticate()
    }
  }
}).state('store.product', {
  url: '/stores/:storeId/products/:productId/',
  views: {
    content: {
      templateUrl: 'product.html',
      controller: 'ProductCtrl'
    }
  },
  resolve: {
    _config: function ($transition$) {
      const storeId = $transition$.params().storeId
      return {
        storeURL: `${APP_SETTINGS.ENDPOINT_BASE}/stores/${storeId}/`,
      }
    },
    _store: function (_config, SettingsService, _auth) {
      const storeURL = _config.storeURL
      return SettingsService.fetchStore(storeURL)
    }
  }
})

@eddiemonge @nateabele @christopherthielen was following this https://github.com/angular-ui/ui-router/issues/1903 Is this still relevant? Do i need to add ResolvePolicy? Checking the docs here mentions that resolves for parent states are fetched before resolves for child states. .

Even after injecting the _auth promise returned from the parent, the SettingsService.fetchStore is not waiting for the _auth to complete. Inputs would be of great help.

shirazz commented 5 years ago

@GhazanfarKhan did you find a fix..

GhazanfarKhan commented 5 years ago

No I solved it in different way.

shirazz commented 5 years ago

@GhazanfarKhan out of ui-router?

GhazanfarKhan commented 5 years ago

No but logics were changed because of this.

shirazz commented 5 years ago

@eddiemonge @nateabele @christopherthielen sorry guys. it was my mistake. i had an api call in the run function which troubled me.. @GhazanfarKhan thanks for your help.

GhazanfarKhan commented 5 years ago

Glad to see that.

vort3xxx commented 5 years ago

You were calling $state.go inside of a resolve block, which is generally a bad idea. You'll see a transition superseded warning in a developer log whenever you do that. Resolve should just be used to obtain async data, not for router flow control. The appropriate place for that flow altering behavior would be via the return value of a transition hook, defined separately.