AngularJS: when $location changes path and actual path has Query String, it causes that new path is loaded twice times

Radek Anuszewski
3 min readMay 14, 2016

--

TL;DR

In my company we had a problem with $location’s path() method — when in current path Query String was present, the change of path happened twice (to exactly the same new path), first time from path with Query String and second time from path without Query String. The solution was to clear Query String with $location’s search() method by setting it to null right before path() method is called. I will be grateful if you write in comments if something like this happened to you.

Doing additional job while before path change

Simple path change

Simplest way to change path is to use href attribute of <a> tag, for cases when path is not constant, for example: user clicks “more details” button on product, more details become visible and we need to recalculate Go to details floating button href, ngHref directive from Angular can be used.

Necessity of doing additional job before path change

But sometimes ngHref is not enough. Sometimes we have to $broadcast/$emit an event. Sometimes, we have to update data in services. In general, sometimes we can’t just place things in listener for $destroy event (despite the fact that from AngularJS 1.5.3 we can use $onDestroy hook, which makes $scope unnecessary for cleansing). Sometimes we have to change path directly from controller.

AngularJS $location service

path() method of $location service

Angular’s $location service provides path() method, which is getter/setter method depending on new path parameter presence. In my company, we had to switch from

<a data-ng-href=”{{$ctrl.calculatePath()}}”>Device</a>

to

<a data-ng-href=”” data-ng-click=”$ctrl.goToDevice()”></a>

And in controller we had:

ServerController.prototype.goToDevice = function(){
//do something
this._location.path(this.calculatePath());
}

$location loads new view twice times

But we were very suprised, when we saw that new view was loaded twice. It was a problem, because in new controller device was reloaded, and with combination of fact that we have logic responsible for removing unnecessary reloads second reload was not resolved. For user, it looked like device was not loaded.

Surprising reason of weird behavior

It takes some time unless we figured out what was going on. The reason was that we had Query String in our view, and path change happened twice times:

  1. First, from path with Query String
  2. Second, from path without Query String

Removing Query String form path just before calling path() method

So, then we have understood that we need to remove Query String from path just before we set new path. $location service provides search() method, and we set our parameter to null.

Now, our code looks like this:

ServerController.prototype.goToDevice = function(){
//do something
this._location.search('serverAddress', null);
this._location.path(this.calculatePath());
}

And everything is OK again.

Conclusion

I don’t expect this weird behavior, which is very hard to find. I will be grateful to you if you write in comments if something like this happened to you.

--

--

Radek Anuszewski

Software developer, frontend developer in AltConnect.pl, mostly playing with ReactJS, AngularJS and, recently, BackboneJS / MarionetteJS.