12

I just got a request from our QA team, which I think sounds ridiculous. Here it goes: suppose you are already on the 'about' state/page in the angular-based app, and when you click on the 'about' state url again from the top menu, you want the 'about' page to reload. The about page does not fetch data from anywhere, by the way, a reload is simply equivalent to a blink.

For the state config in my angular app is like this:

.state('about', {
  url: '/about',
  templateUrl: '/path/to/about.html',
  controller: 'aboutCtrl as aboutView'
});

And in the top menus, we have a link pointing to this state:

<a ui-sref="about">About</a>

I have tried many things to get this to work: clicking the link triggers the reload of the same state.

Things like $state.go('about', {}, {reload: true}); or $state.transitionTo('about', {}, {reload: true}); don't work, because the links are static.

One last resort I am currently trying is to manipulate the reload thing in the run phase of Angular by listening to '$stateChangeSuccess' event, but I don't think it will work, because there's no state change at all if you click on the 'about' link while you are right on that state.

Is there any ways to work around this? Thanks

TonyW
  • 18,375
  • 42
  • 110
  • 183
  • 1
    I don't think that reloading the about page (which I'm assuming is static) is a good way to go for several reasons - your app should just indicate to the user that they're already on that page. A good example is Material Design's animation when you click on the same tab over and over - https://material.angularjs.org/latest/#/demo/material.components.tabs – JaKXz Sep 24 '15 at 19:57
  • or another strategy I have been thinking is to make that link unclickable (not hyperlinked) when the user is on that state already so this will force the user to refresh the browser, but I don't really want to introduce unnecessary logic in my controller. – TonyW Sep 24 '15 at 20:12

2 Answers2

19

There is an option attribute called ui-sref-opts that comes with the UI Router. I faced the same problem and it solved it.

Eg: <a ui-sref="home" ui-sref-opts="{reload: true}">Home</a>

Docs URL : UI Router DOcs

Siv
  • 206
  • 2
  • 2
7

You're right, I can't get any state change events to fire either once already in that state. Until, and if that functionality becomes available to use through that api someday, here's a semi-hacky solution for this. We can just leverage ng-click and use some silly logic to appease QA (in your case). Also, I don't know your controller implementation, so I placed my suggestion on $rootScope in .run in this example for simplicity and visibility, but integrate accordingly if you choose to do so. Observe the following example...

<a ui-sref="about" ng-click="sillyQA()">About</a>

.run(['$rootScope', '$state', function($rootScope, $state) {

    $rootScope.sillyQA = function() {
        if($state.current.name === 'about') {
            $state.go('about', {}, { reload: true });
        }
    }

    // -- just to see our about => about state 'change'
    $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
        console.log('toState:   ' + toState.name );
        console.log('fromState: ' + (fromState.name || 'Just got there! click again!'));
    })
}]);

JSFiddle Link - demo

scniro
  • 16,844
  • 8
  • 62
  • 106
  • Thank you, nicely explained! I was more irritated when I received that request from QA. Because the user can always refresh the browser window if reload is needed. I don't see a point of clicking the same link again to reload it. LOL – TonyW Sep 24 '15 at 20:10
  • @TonyGW I hear where you're coming from! I can only imagine a situation where there is a constant feed, such as the newest questions on SO. I could click the logo all day long if I wanted to "refresh" my feed, rather than explicitly refreshing my browser. Either way happy coding and I am glad this was able to help :) – scniro Sep 24 '15 at 20:16
  • Actually, the page contains a form for user input only. It doesn't receive any data from anywhere. QA people drive me crazy sometimes... – TonyW Sep 24 '15 at 20:18
  • I honestly do not think this should be an accepted answer because there is a good reason for state change events not firing when you're in that state (like, one of the fundamental things behind single-page applications). This is also pretty poor practice in AngularJS/ui-router because you're adding unnecessary logic overhead to your controller, or in the worst case `$rootScope`. – JaKXz Sep 26 '15 at 05:08
  • 1
    Thanks for your input. I thought I made it pretty apparent that `$rootScope` was only for simple demonstration and to "implement accordingly" because the OP didn't share any controller logic. Also, if you read the question, this isn't about best practice, it's about solving a unique situation given a requirement. If you don't think this should be the accepted answer feel free to post your own. Enlighten us. – scniro Sep 26 '15 at 14:41