It's the strangest thing, I found the code that does exactly what I want: using ui-router to change the displayed URL without reloading the page. This is it:
$state.transitionTo($state.current, args, { location: true, inherit: false, notify: false});
The problem is, it only works the first time. After that line is called a second time, angular enters the apply/digest loop & my page breaks. The error shown in the console is:
TypeError: Cannot read property '$$nextSibling' of null
at Scope.$digest (angular.js:12569)
at Scope.$apply (angular.js:12805)
at HTMLDivElement.<anonymous> (angular.js:19138)
at HTMLDivElement.jQuery.event.dispatch (jquery.js:4641)
at HTMLDivElement.elemData.handle (jquery.js:4309)