My single page application loads a home page and I want to display a series of ideas. Each of the ideas is displayed in an animated flash container, with animations displayed to cycle between the ideas.
Ideas are loaded using $http:
$scope.flash = new FlashInterface scope:$scope,location:$location
$http.get("/competition.json")
.success (data) ->
$scope.flash._init data
However, to benefit from history navigation and UX I wish to update the address bar to display the correct url for each idea using $location:
$location.path "/i/#{idea.code}"
$scope.$apply()
I am calling $apply here because this event comes from outwith the AngularJS context ie Flash. I would like for the current controller/view to remain and for the view to not reload. This is very bad because reloading the view results in the whole flash object being thrown away and the preloader cycle beginning again.
I've tried listening for $routeChangeStart to do a preventDefault:
$scope.$on "$routeChangeStart", (ev,next,current) ->
ev.preventDefault()
$scope.$on "$routeChangeSuccess", (ev,current) ->
ev.preventDefault()
but to no avail. The whole thing would be hunky dory if I could figure out a way of overriding the view reload when I change the $location.path.
I'm still very much feeling my way around AngularJS so I'd be glad of any pointers on how to structure the app to achieve my goal!
From this blog post:
I needed to do this but after fussing around trying to get the
$locationChange~
events to get it to work I learned that you can actually do this on theroute
usingresolve
.Instead of updating the path, just update query param with a page number.
set your route to ignore query param changes:
and in your app update
$location
with:The $locationChangeSuccess event is a bit of a brute force approach, but I found that checking the path allows us to avoid page reloads when the route path template is unchanged, but reloads the page when switching to a different route template:
Adding that code to a particular controller makes the reloading more intelligent.
Edit: While this makes it a bit easier, I ultimately didn't like the complexity of the code I was writing to keep friendly looking URL's. In the end, I just switched to a search parameter and angular handles it much better.
With AngularJS V1.7.1,
$route
adds support for thereloadOnUrl
configuration option.If route
/foo/:id
hasreloadOnUrl
=false
set, then moving from/foo/id1
to/foo/id2
only broadcasts a$routeUpdate
event, and does not reload the view and re-instantiate the controller.My solution was to use the $routeChangeStart because that gives you the "next" and "last" routes, you can compare them without the need of an extra variable like on $locationChangeSuccess.
The benefit is being able to access the "params" property on both "next" and "last" routes like
next.params.yourproperty
when you are using the "/property/value" URL style and of course use$location.url
or$location.path
to change the URL instead of$location.search()
that depends on "?property=value" URL style.In my case I used it not only for that but also to prevent the route to change is the controller did not change:
Personally I feel like AngularJS should provide a way to control it, right now they assume that whenever you change the browser's location you want to change the route.