Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular UI router's "resolve" fires twice

I am using angular ui router to handle some routing on my frontend. This is what my routing code looks like.

// angular config

$stateProvider.state('app', {
    templateUrl: '/static/partials/home.html',
    controller: 'NavCtrl'
});

$stateProvider.state('app.reader', {
    url : '/reader/*path?start&end&column&page',
    templateUrl: '/static/partials/reader.html',
    resolve : {
        panelContent : [
            '$state', '$stateParams', '$http',
            function ($state, $stateParams, $http) {
                alert('resolving panel Content');
                return [];  // simplest thing possible to illustrate my point
            }
        ]
    },
    controller: 'ReaderCtrl'
});

/// etc etc

$urlRouterProvider.otherwise('/reader/');

My html makes use of multiple nested views, I'll try and illustrate as best I can

index.html

<html>
    <div ui-view></div>     <!-- /static/partials/home.html gets injected here -->
</html>

/static/home.html

<html>
    <!-- some side bar stuff -->

    <!-- reader -->
    <div ui-view></div>    <!-- /static/partials/reader.html gets injected here -->
</html>

So I've got multiple levels of nesting going on

-- index.html
    -- home.html
        -- reader.html

Now, when I load the page for the first time, my alert message

alert('resolving panel Content');

fires just once.. that makes sense. However, let's say I click "next page" inside my pagination..

<!-- inside /static/partials/reader.html -->   

<uib
    pagination total-items= "totalItems"
    ng-model= "pageNumber"
    ng-change= "pageUpdate"
    max-size= "maxPageNumbersDisplayed"
></uib>

this eventually fires a function inside my "ReaderCtrl"

$scope.pageUpdate(page) {
    $state.go( '.', {page: page}); 
}   

This updates the url, from going to something like this

/#/reader/<my path>

to something like this

/#/reader/<my_path>?page=2

Now for the part that has me tearing my hair out.

I get back to the "resolve" code block in the reader section of my routing.

The alert message happens twice.

By doing a bit of debugging in the web console, I discovered that the order goes

 1) alert message in resolve
 2) travel through the entirety of ReaderCtrl
 3) lots and lots of angular calls
 4) alert message (2nd time)
 5) travel through entirety of ReaderCtrl a second time.

You might be inclined to know what is going on in NavCtrl, but I am not making any calls there. All that is in NavCtrl are functions that ReaderCtrl can inherit, in order to update the scope for /static/partials/home.html

So really, it appears as though I am stuck on step 3 here.

Does anyone have any ideas as to why my resolve block appears to be firing twice?

edit:

after a bit more debugging, I have seemed to figure out that the order goes something like this, starting right after the "updatePage" function executes.

1) first "resolving message"
    -- the url has not yet changed
2) second "resolving message"
    -- the url appears to have changed very shortly before this message

So, I guess my question now is... why does

$state.go('.', args);

NOT change the url before the first alert fires, but DOES change the url at/near the second alert?

edit 2: could not end up fixing my issue, so I sort of hacked around it for the time being... I essentially made a function that did what I assume $state.go() was doing behind the scenes, and constructed the url.

function _mk_url(args) {

    var url = "/reader";

    var pageNumber = args.pageNumber || 1;
    url += "?page=" + pageNumber;

    var columns = args.columns || [];
    columns.forEach(function(d) {
        url += "&column=" + d;
    });

    //etc..

    return url;
}

var args = {"columns" : ["a", "b", "c"], "pageNumber" : 2};
var url = _mk_url(args);
$location.url(url);
like image 216
Zack Avatar asked Jan 26 '16 19:01

Zack


Video Answer


1 Answers

I was having this problem and found out it was because I was calling my resolve function manually somewhere else in the code. Search your code for panelContent() and you may find where it's getting triggered again.

like image 85
jlewkovich Avatar answered Sep 23 '22 14:09

jlewkovich