1

I do have a webpage based on jHipster template and issue with browser back button.

Let's say that I do have two pages

  • Articles list (/articles/{id},{name}, category id, category name)
  • Article details (/article/{id}, article id)

Articles list page displays category name set in the scope:

js:

$scope.name = $stateParams.name; 

html:

<div>{{ name }}</div>
<ul>
<li ng-repeat="item in items">
    <a ui-sref="article({id: item.id})">{{ item.title }}</a>
</li>
</ul>

When I enter this page it works perfectly fine. Category name is displayed, then I use the link to navigate to the article. Everything works perfectly fine. Problems start when I use browser history back button.

It does load article list state, it does download items using a service and displays the list, it doesn't show category name though. Just plain {{ name }} is being displayed.

Chrome shows weird error but Firefox shows more specific issue:

Error: [$rootScope:inprog] $digest already in progress
http://errors.angularjs.org/1.4.5/$rootScope/inprog?p0=%24digest

While I do understand why it might be a problem and it's clearly described in the other SO question, I don't understand what might be the root of the problem and therefore I am unable to resolve it.

Community
  • 1
  • 1
SirKometa
  • 1,857
  • 3
  • 16
  • 26

1 Answers1

0

This sounds like a problem caused by executing AngularJS code from outside events. For example, you need to use $scope.$apply(...) to execute code from a window.resize event.

This might be working correctly during normal app usage, but when you go back in history the code is executed while in a digest loop. This triggers the error, and if this error happens during compile the template ends up with incomplete bindings. Which is why you see {{name}} on the page.

Here is a function that will fix the problem.

    /**
     * @param {angular.IScope|angular.IRootScopeService} $scope
     * @param {function()} func
     */
    function safeApply($scope, func) {
        if ($scope.$$phase) {
            func();
        }
        else {
            $scope.$apply(function () {
                func();
            });
        }
    };

You need to find and replace $scope.$apply(function(){....}) with safeApply($scope,function(){....});

The safeApply will check if a digest is already in progress. If there is no digest it knows the method was called from outside Angular, and it will call $apply. Otherwise, it executes the callback as is.

The issue might not be in your app. It could be something from the stack you're using. You'll need to do some digging to find out where the problem is. If the issue is in the stack. You should report it to the authors so that other people can benefit.

Reactgular
  • 52,335
  • 19
  • 158
  • 208