maaartinus maaartinus - 2 months ago 7
AngularJS Question

Prevent search changes from spamming history

I'm using links like

#!/OrderList?id=123
, which shows the list of all orders and more details of the order 123. With
reloadOnSearch=false
and watching
$routeUpdate
it works fine, except for one thing: All such links get put into the browsers history, while I'd prefer to have only one such link there. For example, instead of

#!/OrderList?id=123
#!/OrderList?id=124
#!/OrderList?id=125
#!/AnotherList?id=678
#!/AnotherList?id=679


just the last member of each group, i.e.,

#!/OrderList?id=125
#!/AnotherList?id=679


I'm aware of
$location.replace()
, but I can't see where to place it when the change happens via following a link. I tried to place it in
$scope.$on("$routeUpdate", ...)
, but it did nothing, probably because it's too late when the route has already changed.

I'm not using neither
router-ui
nor the HTML5 mode (just plain
angular-route
).

Answer

I wasn't satisfied with any answer and after quite some debugging I found this solution:

.run(function($rootScope, $location) {
    var replacing;

    $rootScope.$on("$locationChangeStart", function(event, newUrl, oldUrl) {
        if (oldUrl === newUrl) return; // Nobody cares.

        // Make urls relative.
        var baseLength = $location.absUrl().length - $location.url().length;
        newUrl = newUrl.substring(baseLength);
        oldUrl = oldUrl.substring(baseLength);

        // Strip search, leave path only.
        var newPath = newUrl.replace(/\?.*/, "");
        var oldPath = oldUrl.replace(/\?.*/, "");

        // Substantial change, history should be written normally.
        if (oldPath !== newPath) return;

        // We're replacing, just let it happen.
        if (replacing) {
            replacing = false;
            return;
        }

        // We're NOT replacing, scratch it ...          
        event.preventDefault();

        // ... and do the same transition with replace later.
        $rootScope.$evalAsync(function() {
            $location.url(newUrl).replace();
            replacing = true;
        });
    });
})
Comments