AngularJS, using routes without refreshes on back button

夙愿已清 提交于 2019-12-09 09:10:26

问题


I'm using angularJS to build a simple single page application using AJAX, but I'm running into a problem when users use the native back button.

angular.module('myApp', ['ionic', 'myApp.controllers', myApp.services])

.config(function ($routeProvider, $locationProvider) {

    $routeProvider.when('/home', {
       templateUrl: 'templates/feed.html',
       controller: 'MenuCtrl',
       reloadOnSearch: false
   });

   $routeProvider.when('/checkin/view/:id', {
       templateUrl: 'templates/checkin.html',
       controller: 'MenuCtrl'
    });

    $routeProvider.otherwise({
        redirectTo: '/home'
    });


     $locationProvider.html5Mode(true)

})

UPDATE: moved $http out of controls per feedback, and suggestions:

And my services.js file:

angular.module('myApp.services', [])

 .factory('FeedService', ['$http', function($http){
   var state = {};

  var loadFeed = function(){
       $http({
           method: 'GET',
           url: 'http://api.example',
         }).success(function(data){
        // With the data succesfully returned, call our callback
           state = data.response;
           console.log(data);
        }).error(function(){
           alert("error");
       });
   };

   loadFeed();

   return {
       getState: function(scope){
           return state;
       }
    };
}])

And my controller.js file:

angular.module('myApp.controllers', [])

.controller('MenuCtrl', function($scope, $http, $location, FeedService) { 
    // feedback per second answer
    $scope.items  = FeedService.getState();

})

.controller('CheckinCtrl', function($scope, $routeParams) {
    $scope.checkin_id = $routeParams.id;
    console.log($routeParams.id);
});

My main index.html is setup like this:

 <body ng-app="untappd">
   <div ng-view></div>
 </body>

This works great from navigation from a feed (/home), to a check-in page (/checkin/view/:id) but, once the user hits the native back button on the browser or using window.history.back(), code in the controller is called again, which makes the AJAX call to pull down the user's friend feed. Should I be using ng-show instead of using ng-view for this use case, and create individual "pages" for each content I want to show? I was concerned with the performance, but it appears that I can't get data to persist in each ng-view without it having to re-call the templates. Any guidance here?

UPDATE: I have changed this to incorporate the Best Practices, by adding the $http request at the services level, instead of the controller level. I still run in to the issue of the getState request being fired, before the the AJAX of the $http is complete, thus having an empty state, and nothing to render the $scope.


回答1:


Yep, the Back button and the the Refresh button are a real pain. You have two choices:

  1. You keep things simple and just allow your state to be fetched for each location change. This treats a user triggered back button click or a refresh as any normal location change. Data re-fetching can be mitigated by http caching.

  2. You maintain your own state on the client and restore it when required, possibly using SessionStorage to keep things clean.

I chose the latter option and it all works just fine for me. See these self answered questions for detailed code examples.

  • How do I get the Back Button to work with an AngularJS ui-router state machine?
  • How do I handle page refreshing with an AngularJS Single Page Application



回答2:


Use a service to keep a singleton state, which exposes functions to get/reload/etc. Here is a very simple example, just to get you started:

.factory('FeedService', ['$http', function($http){
    var state = {};

    var loadFeed = function(){
        $http.get('http://api.example.com').then(function(result){
            state.feed = result.items;                
        });
    };

    // load the feed on initialisation
    loadFeed();

    return {
        getState: function(){
            return state;
        }
    };
}])

.controller('MenuCtrl', ['$scope', 'FeedService', function($scope, FeedService) {        
    // assign the feed container to any scope that you want to use for view
    $scope.cont = FeedService.getState();
})

Again, this is very basic, and is simply showing you how you can use a service to store a persistent state between routes.




回答3:


if your parameter 'id' in the route contains any character that is being decoded during the http request (like ' ' => '%20') then your route will not work. try to perform encodeURIComponent() on your string before using it for the routing.



来源:https://stackoverflow.com/questions/23457904/angularjs-using-routes-without-refreshes-on-back-button

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!