How to preserve ui-router parameters on browser re

2019-06-21 23:36发布

am using angular ui-router to manage states of my SPA. I have this route:

    .state('index.administration.security.roleEdit', {
                url: '/roleEdit',
                templateUrl: 'app/administration/security/role/roleEdit.html',
                controller: 'roleEditCtrl',
                controllerAs: 'roleEditCtrl',
                params: { data: null },
                resolve: {
                    role: function ($stateParams) {
                        return angular.fromJson($stateParams.data);
                    },
                    modules: function (securityService) {
                        return securityService.getAllModules();
                    }                       
                }
            })

Also, I'm passing 'data' parameter as json object to the state. Now when i first load this state, everything is fine. But when i do browser refresh (F5 key) the $stateParams.data is null in the resolve function of the state.

How can I solve this? I see these possible solutions: 1. persist somehow parameters 2. override browser refresh (don't know how) to stop the browser refreshing the app. 3. on refresh goto other sibling state.

Please help

UPDATE Ok, I set data like this:

vm.editRole = function(roleId){
     var role = dataService.getRoleById(roleId).then(function(result){
           $state.go('roleEdit', {data:angular.toJson(result)});
           });
}

UPDATE 2 The roleEdit Controller looks like this:

(function(){
    angular.module('app.administration').controller('roleEdit', 
    ['role','modules', '$scope', 'securityService', '$state', roleEditCtrl]);

    function roleEditCtrl('role', 'modules',$scope, securityService, $state){
        var vm = this;
        vm.roles = roles;
        vm.originalRole = angular.copy(role);
        vm.modules=modules;
        vm.saveChanges = _saveChanges;
        vm.cancel = _cancel;

        return vm;

        function _saveChanges(){
            securityService.UpdateRole(vm.role).then(function(result){
                $staste.go('^.roles');
            }
        }

        function _cancel(){
            vm.role = angular.copy(vm.originalRole);
            $sscope.roleEditForm.$setPristine();            
        }
    }
})();

2条回答
贪生不怕死
2楼-- · 2019-06-21 23:39

Had the same problem, leaving this here in case someone else needs it. Solved it by using localStorage.

I've set this as a part of app's run method

$rootScope.$on('$stateChangeSuccess', function (event, toState) {
    localStorage.setItem('__stateName', toState.name);
});

Now, depending on your app's structure you might want to consider putting this someplace else, but in my case I had parent AppController surrounding all child controllers, so this part of the code went there.

var previousState = localStorage.getItem('__stateName');
previousState && $state.go(previousState) || $state.go(<SOME_OTHER_ROUTE>);

Basically, when user hits browser refresh, AppController get initialized from the start (before child controllers), firing the state transition immediately if there was one. Otherwise, you'd go to some other state of yours.

查看更多
啃猪蹄的小仙女
3楼-- · 2019-06-21 23:43

I would stay away from option 2. You don't want to mess up a browser's expected behavior.

Maybe you could refactor your data into your resolve object ala:

resolve: {
           role: function ($stateParams) {
               return angular.fromJson($stateParams.data);
           },
           modules: function (securityService) {
               return securityService.getAllModules();
           },
           data: function (dataService) {
               return dataService.retrieveStoredData();
           }

Where your dataService would be a service you use to store that data if it really is that important (through cookies or localstorage).

There is no reasonable way to expect that field to be populated on browser refresh if you previously executed javascript to pass stateful values to it.

查看更多
登录 后发表回答