The problem you're having is a bit related to the functioning of Javascript, another bit to how Angular works. As Einer says, the $ apply is invoked by Angular in all cases, and if you try to call $ apply in another $ apply, throw away the error you're having.
In some cases it is necessary to call back the $ apply since Angular can not detect changes that are outside of its scope.
One solution for these cases is to force Javascript to generate another "round" or "shift" of execution.
In my case I have had situations in which I needed to force a refresh and for those cases, in angular 1 and 2, it has helped me to do this:
setTimeout(function() {
$scope.$apply(function() {
$scope.name = "Timeout called!";
});
}, 0);
This note ( link ) helped me a lot to understand when and how to use $ apply in a way that does not become an anti-pattern in your application.
Here is an example of this applied theory: link
In the example you will be able to see several things, when it is updated and when it is not.
Just one more clarification, always before applying this type of solutions, first check your logic, in my case, in 8 out of 10, I found another solution that fixed the problem.
Second clarification, instead of setTimeout, it is convenient to use $ timeout , which already includes a $ apply in the code, but in the answer I wanted to demonstrate a bit the reason for the error and how to solve it in accordance to its causes.
I hope it is of your use, otherwise, do not hesitate to ask again.