Reloading current state - refresh data

Problem

I'm using Angular UI Router and would like to reload the current state and refresh all data / re-run the controllers for the current state and it's parent.

I have 3 state levels: directory.organisations.details

directory.organisations contains a table with a list of organisations. Clicking on an item in the table loads directory.organisations.details with $StateParams passing the ID of the item. So in the details state I load the details for this item, edit them and then save data. All fine so far.

Now I need to reload this state and refresh all the data.

I have tried:

 $state.transitionTo('directory.organisations');

Which goes to the parent state but doesn't reload the controller, I guess because the path hasn't changed. Ideally I just want to stay in the directory.organisations.details state and refresh all data in the parent too.

I have also tried:

$state.reload()

I have seen this on the API WIKI for $state.reload "(bug with controllers reinstantiating right now, fixing soon)."

Any help would be appreciated?

Problem courtesy of: Holland Risley

Solution

This solution works in AngularJS V.1.2.2:

$state.transitionTo($state.current, $stateParams, {
    reload: true,
    inherit: false,
    notify: true
});
Solution courtesy of: Holland Risley

Discussion

Everything failed for me. Only thing that worked...is adding cache-view="false" into the view which I want to reload when going to it.

from this issue https://github.com/angular-ui/ui-router/issues/582

Discussion courtesy of: Hans

That would be the final solution. (inspired by @Hollan_Risley's post)

'use strict';

angular.module('app')

.config(function($provide) {
    $provide.decorator('$state', function($delegate, $stateParams) {
        $delegate.forceReload = function() {
            return $delegate.go($delegate.current, $stateParams, {
                reload: true,
                inherit: false,
                notify: true
            });
        };
        return $delegate;
    });
});

Now, whenever you need to reload, simply call:

$state.forceReload();
Discussion courtesy of: M K

@Holland Risley 's answer is now available as an api in latest ui-router.

$state.reload();

A method that force reloads the current state. All resolves are re-resolved, controllers reinstantiated, and events re-fired.

http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$state

Discussion courtesy of: Muthukannan Kanniappan

You can use @Rohan answer https://stackoverflow.com/a/23609343/3297761

But if you want to make each controller reaload after a view change you can use

myApp.config(function($ionicConfigProvider) { $ionicConfigProvider.views.maxCache(0); ... }
Discussion courtesy of: EduLopez

if you want to reload your entire page, like it seems, just inject $window into your controller and then call

$window.location.href = '/';

but if you only want to reload your current view, inject $scope, $state and $stateParams (the latter just in case you need to have some parameters change in this upcoming reload, something like your page number), then call this within any controller method:

$stateParams.page = 1;
$state.reload();

AngularJS v1.3.15 angular-ui-router v0.2.15

Discussion courtesy of: MarcoSantana

Probably the cleaner approach would be the following :

<a data-ui-sref="directory.organisations.details" data-ui-sref-opts="{reload: true}">Details State</a>

We can reload the state from the HTML only.

Discussion courtesy of: Vaibhav Pachauri

I had multiple nested views and the goal was to reload only one with content. I tried different approaches but the only thing that worked for me is:

//to reload
$stateParams.reload = !$stateParams.reload; //flip value of reload param
$state.go($state.current, $stateParams);

//state config
$stateProvider
  .state('app.dashboard', {
    url: '/',
    templateUrl: 'app/components/dashboard/dashboard.tmpl.html',
    controller: 'DashboardController',
    controllerAs: 'vm',
    params: {reload: false} //add reload param to a view you want to reload
  });

In this case only needed view would be reloaded and caching would still work.

Discussion courtesy of: Dmitriy Nevzorov
$scope.reloadstat = function () { $state.go($state.current, {}, {reload: true}); };
Discussion courtesy of: user7961355

Not sure why none of these seemed to work for me; the one that finally did it was:

$state.reload($state.current.name);

This was with Angular 1.4.0

Discussion courtesy of: BarrySW19

For angular v1.2.26, none of the above works. An ng-click that calls the above methods will have to be clicked twice in order to make the state reload.

So I ended up emulating 2 clicks using $timeout.

$provide.decorator('$state',
        ["$delegate", "$stateParams", '$timeout', function ($delegate, $stateParams, $timeout) {
            $delegate.forceReload = function () {
                var reload = function () {
                    $delegate.transitionTo($delegate.current, angular.copy($stateParams), {
                        reload: true,
                        inherit: true,
                        notify: true
                    })
                };
                reload();
                $timeout(reload, 100);
            };
            return $delegate;
        }]);
Discussion courtesy of: thanos panousis

I know there have been a bunch of answers but the best way I have found to do this without causing a full page refresh is to create a dummy parameter on the route that I want to refresh and then when I call the route I pass in a random number to the dummy paramter.

            .state("coverage.check.response", {
                params: { coverageResponse: null, coverageResponseId: 0, updater: 1 },
                views: {
                    "coverageResponse": {
                        templateUrl: "/Scripts/app/coverage/templates/coverageResponse.html",
                        controller: "coverageResponseController",
                        controllerAs: "vm"
                    }
                }
            })

and then the call to that route

$state.go("coverage.check.response", { coverageResponse: coverage, updater: Math.floor(Math.random() * 100000) + 1 });

Works like a charm and handles the resolves.

Discussion courtesy of: ewahner
$state.go($state.current, $stateParams, {reload: true, inherit: false});
Discussion courtesy of: Weston Ganger

Silly workaround that always works.

$state.go("otherState").then(function(){
     $state.go("wantedState")
});
Discussion courtesy of: Fanchi

for ionic framework

$state.transitionTo($state.current, $state.$current.params, { reload: true, inherit: true, notify: true });//reload

$stateProvider.
  state('home', {
    url: '/',
    cache: false, //required

https://github.com/angular-ui/ui-router/issues/582

Discussion courtesy of: RouR

I had this problem it was wrecking my head, my routing is read from a JSON file and then fed into a directive. I could click on a ui-state but I couldn't reload the page. So a collegue of mine showed me a nice little trick for it.

  1. Get your Data
  2. In your apps config create a loading state
  3. Save the state you want to go to in the rootscope.
  4. Set your location to "/loading" in your app.run
  5. In the loading controller resolve the routing promise and then set the location to your intended target.

This worked for me.

Hope it helps

Discussion courtesy of: Evan Burbidge

I found this to be the shortest working way to refresh with ui-router:

$state.go($state.current, {}, {reload: true}); //second parameter is for $stateParams

Update for newer versions:

$state.reload();

Which is an alias for:

$state.transitionTo($state.current, $stateParams, { 
  reload: true, inherit: false, notify: true
});

Documentation: https://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$state#methods_reload

Discussion courtesy of: Rohan

This recipe can be found in it's original form on Stack Over Flow.