bryan
bryan

Reputation: 9399

Angularjs $rootScope in resolve sometimes not updating in template

For some reason, my $rootScope.user variable in my resolve function does not finish assigning the data before my view.html template loads.

Most of the time, I will be able to do {{ $root.user.uid }} in my template and I will be able to see the variable data, but sometimes it won't show up.

I'm a bit confused on why this would happen because doesn't a resolve have to run FIRST before the template loads?

Does anyone know why this would be happening?

NOTE: If I add a console.log($rootScope.user.uid) before deferred.resolve(); it always shows up, just not showing the variable in the template.

.factory('Auth', function($http, $state, $q, $rootScope) {
    var factory = {workflowItemCheck: workflowItemCheck };
    return factory;

   function workflowItemCheck(workflow_id) { return $http.post('/auth/workflow', {workflow_id:workflow_id}); }
})


.config(function($stateProvider, $urlRouterProvider, $locationProvider) {
    var workflow_item_auth = ['$q', 'Auth', '$rootScope', '$stateParams', function ($q, Auth, $rootScope, $stateParams) { 

        var deferred = $q.defer();

        Auth.workflowItemCheck($stateParams.workflow_id).then(function(data){ 
            $rootScope.user = { uid: data.data.uid };
            deferred.resolve(); 
        }, function(){ deferred.reject(); });

        return deferred.promise;
    }];


    $stateProvider.state(
        'workflow2.view', { 
            url: '/:workflow_id/view', 
            templateUrl: 'pages/templates/workflow/view.html',
        }, 
        controller: 'workflow.view', 
        resolve: { authenticated: workflow_item_auth } 
    })



})

PLEASE NOTE: There is nothing in the controller. This is specifically getting my $rotoScope to the template.

Upvotes: 3

Views: 1716

Answers (3)

Eric
Eric

Reputation: 193

I got one solution which is force that the resolve execute before loading the data into view. As we know, the resolve will be executed before controller if it returns a promise. And the controller is executed before view.

hope this can give you a kind of help

.controller('workflow.view', ['$rootScope', 'authUser', function($rootScope, authUser){
$rootScope.user = { uid: authUser.data.uid };}])

.config(function($stateProvider, $urlRouterProvider, $locationProvider) {
$stateProvider.state(
    'workflow2.view', { 
        url: '/:workflow_id/view', 
        templateUrl: 'pages/templates/workflow/view.html',
    }, 
    controller: 'workflow.view', 
    resolve: { 
        Auth : 'Auth',
        authUser: function(Auth,$stateParams){
           return Auth.workflowItemCheck($stateParams.workflow_id);
        }
    } 
})})

Upvotes: 0

Roan Bester
Roan Bester

Reputation: 71

Because the backend call is async, I believe Angular already went through its digest cycle by the time your backend call completes. So, the binding isn't updated.

In your promise's resolve (where you do $rootScope.user = ..), try and add $rootScope.$apply() right after that, to refresh the bindings.

Upvotes: 0

mcgraphix
mcgraphix

Reputation: 2733

your resolve isn't returning a promise so at the time it is resolving your workflow_item_auth might not be set. If your resolve returns a promise, it won't navigate to your view until it is resolved.

$stateProvider.state(
        'v1', {
            url: '/:workflow_id/view',
            templateUrl: 'view.html',
            resolve: {
                authenticated: function(Auth, $rootScope, $stateParams) {
                    return Auth.workflowItemCheck($stateParams.workflow_id).then(function(data) {
                        $rootScope.user = {uid: data.data.uid};
                        return data;
                    });
                }
            }
        }
);

EDIT - Actually I see that you are returning a promise there. I still think there is potentially a timing issue there. I would still do it as I explained above.

Upvotes: 3

Related Questions