0

I have implemented Angular UI-Router for state management in my app. It works fine when the user clicks on the various parts of the page and the appropriate information loads in the view. However, when the user refreshes the page from a state other than the initial state the page loads as if it were in the initial state. Here are the details...

This is a catalog of posts and we have the initial view which lists all the posts available. Then we have sections and subsections. If the user clicks for either of these then only the posts with the appropriate categories will be displayed.

Here is the config:

app.config(function($stateProvider, $urlRouterProvider) {

  $stateProvider
    .state('initial', {
      url: '/',
      templateUrl: 'list_posts.html'
    })
    .state('category', {
      url: '/:category',
      templateUrl: 'list_posts.html'
    })
    .state('subcategory', {
      url: '/:category/:subcategory',
      templateUrl: 'list_posts.html'
    })
    .state('singlePost', {
      url: '/:category/:subcategory/:post',
      templateUrl: 'single_post.html'
    });

  $urlRouterProvider.when('', '/');

});

And my controller works like this:

I have a variable called

$scope.posts = [];

Then I call a service function in order to populate the array with all the post objects.

Then I set up a listener for a successful state change

  $scope.$on('$stateChangeSuccess', function () {

    $scope.updatePosts( $stateParams );

  });

So effectively, we start at the '/' route and if the user clicks to load a specific section then the url will change and the name of that section will be in $stateParams. Then the listener fires and calls the updatePosts method. This method will empty posts array and reload it with only the posts that have that section name as a category. Once this array is updated then the view changes to reflect the new filtered list of posts.

Here is the updatePosts function

  $scope.updatePosts = function ( cats ) {
    var length = $scope.dataset.length;
    $scope.posts = [];

    if ( Object.keys(cats).length == 0 ) {
      console.log('empty cats object');
      $scope.posts = $scope.dataset;
      console.log($scope.posts);
    }
    else if ( Object.keys(cats).length == 1 ) {
      console.log('one category');
      console.log(cats);
      for (var i = 0; i < length; i++) {
        if ( $scope.dataset[i].category_slugs.indexOf( cats.category ) > -1 ) {
          $scope.posts.push( $scope.dataset[i] );
        }

      }
    }
    else if ( Object.keys(cats).length == 2 ) {
      console.log('two categories');
      console.log(cats);
      for (var i = 0; i < length; i++) {
        if ( $scope.dataset[i].category_slugs.indexOf( cats.category ) > -1 && $scope.dataset[i].category_slugs.indexOf( cats.subcategory ) > -1 ) {
          $scope.posts.push( $scope.dataset[i] );
        }

      }
      console.log($scope.posts);
    }

  };

Again, the issue is that this all works just fine until the user decides to refresh the page while it is in a 'category', 'subcategory', or 'singlePost' state. Instead of returning to the appropriate list of filtered posts it will just revert back to the initial state even though the url says otherwise.

Any suggestions on where the problem lies?

Thank you

user2623706
  • 527
  • 1
  • 6
  • 19
  • I'm not sure I'm understanding what `when` is supposed to do from the docs, but if you replace `$urlRouterProvider.when('', '/');` with `$urlRouterProvider.otherwise('/');`, does that help? It looks like when is supposed to redirect given a url to match, and I'm not sure what passing in an empty string to match against would do. – Shaun Mar 30 '16 at 18:02
  • The change you suggested does have the same effect as what I originally had. That was actually for something else I was dealing with but is now fixed. This does not address the question I posed here though. – user2623706 Mar 30 '16 at 18:08
  • What I am asking is if one goes to www.myurl.com it will load the catalog and all the posts. If they click the link to go to a specific category the url will then change to www.myurl.com/category and the proper posts will load. However if they refresh from www.myurl.com/category the page will reload and the url will remain www.myurl.com/category BUT the posts will load as if state was still at www.myurl.com. Does this make sense? – user2623706 Mar 30 '16 at 18:09

2 Answers2

0

When you are doing a hard refresh is it going inside stateChangeSuccess event? if yes are you able to see your $stateParams what ever you have in url?

 $scope.$on('$stateChangeSuccess', function () {
    console.log($stateParams);
    $scope.updatePosts( $stateParams );

  });
Venkat
  • 551
  • 6
  • 17
  • Yes I am. I went ahead and edited my original question to include the updatePosts function. It all works fine while navigating regularly through the page. But after a hard refresh yes the $stateChangeSuccess event fires and the $stateParams are the same as what is in the url. Consequently the updatePosts function also gets called and again the $stateParams are the same as whats in the url. – user2623706 Mar 30 '16 at 20:27
  • Below thread has similar conversation.check this. http://stackoverflow.com/questions/32602345/angularjs-ui-router-stateparams-invisible-loses-on-page-refresh – Venkat Mar 30 '16 at 20:48
  • Not quite sure its the same. In that thread they are talking about caching data that gets lost on refresh. In my case after refresh we still have the data we want which is the $stateParams from the url which are still correct. But for some reason the updatePosts function is not working properly despite getting called with the correct parameters. – user2623706 Mar 30 '16 at 21:32
0

try following changes in .config()

.state('category', {
  url: 'category/:category',
  templateUrl: 'list_posts.html'
})

In your code, there is no exact match's for any state and will execute .otherwise() option. For example, consider you are refreshing from category state.Let's assume url is 'localhost/books' where books stand for /:category.Since there is no state with url '/books',will cause to choose otherwise();

ksyCho
  • 89
  • 4