Equivalent to reloadOnSearch:false for $location.path?

1,968 views
Skip to first unread message

Nick R

unread,
Mar 13, 2012, 6:54:49 AM3/13/12
to ang...@googlegroups.com
I was playing around with $route today and with the reloadOnSearch:false feature and I found it pretty useful.  In fact, I even went so far as to alter my copy of Angular to set reloadOnSearch:false for all routes.  That way I could put a bunch of neat global mode-switching features into the url via $location.search and handle them in the $on '$routeChange' handler on the root controller.  The sort of features I targeted here were fullscreen and other viewing preferences that affected the application no matter what you were looking at.  Implementing them on the root controller kept me from having to touch every controller or every route with this information.

The downside of this is that my urls don't look as good with all those querystring arguments in them.  And that got me thinking -- why can't other routing information work the same way reloadOnSearch does?  What if, if you changed $location.path in such a way that didn't end up changing the current controller, you could have it call $on '$routeChange' with the new routing variables instead of destroying and re-creating the controller?

Another big reason why I started using reloadOnSearch:false is so that my inner scrollable content wouldn't be jumped back to the top every time I wanted to change the url.  For example, if you were scrolling through a sidebar and picking out items that altered the url, it would be frustrating if that sidebar kept scrolling back to the top.  Using querystring arguments here looks even uglier than it does with global features though.


While I'm on the subject of routing, it would be really nice if you could specify some extra parameters to be passed along in the route params for a controller.  The situation I keep getting into is this one:

$route.when('/specific_section/specific_subsection', controller:SpecialController);
$route.when('/specific_section/specific_subsection_2', controller:SpecialController);
$route.when('/:section/:subsection', controller:DefaultController);

Here I am trying to re-use SpecialController for two special cases to my default routing.  Unfortunately, I have no way of knowing which special case was chosen, since it doesn't pass on the section and subsection variables that the default controller does.  If controller inheritance was a thing, I could create two different controllers that both inherited the behavior of SpecialController so I wouldn't have to repeat it.  But currently it seems like SpecialController has to re-parse the url to figure out where it is, or perhaps I have to copy-paste it to create both versions.  This problem could also be solved by allowing regular expression captures in routes, as that would let me restrict when this controller was used but still pass along the information I matched against.


Peter Bacon Darwin

unread,
Mar 13, 2012, 7:21:35 AM3/13/12
to ang...@googlegroups.com
I might be wrong but I think that controller inheritance will work in 10.7 (1.0) since instead of injecting the controller into the scope the controller is now instantiated and the scope is injected into the controller.

Also you can add extra stuff to the route when you define it and extract it in the $afterRouteChange event, perhaps adding something to the routeParams for your controller to see?

Pete



--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To view this discussion on the web visit https://groups.google.com/d/msg/angular/-/RLQeHNFG9ksJ.
To post to this group, send email to ang...@googlegroups.com.
To unsubscribe from this group, send email to angular+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/angular?hl=en.

Misko Hevery

unread,
Mar 13, 2012, 12:58:11 PM3/13/12
to ang...@googlegroups.com
Hi Nick,

Thanks for this very in depth analysis, But was there a question hidden in there someplace? I think I missed it.

-- misko

Nick R

unread,
Mar 13, 2012, 9:41:01 PM3/13/12
to ang...@googlegroups.com
Misko: I asked how to handle some situations and suggested features that would make things easier to deal with.

I thought it would be nice to add something like reloadOnPath:false (based on reloadOnSearch:false) so that angular would not recreate your controller if the new path still routed to the same controller, but instead call $on '$routeChange'.  You could make both this and reloadOnSearch's default values be configurable without editing the angular source code.  This would allow pretty urls without forcing you to re-evaluate your controller every time the url changed.

I also asked how to handle my url situation in 10.6.  If you have two url patterns pointing to the same place, how can you tell which one the router followed?  I thought it would be useful to add extra values into a route expression to be passed on as $routeParams even if they weren't in the url.  That would make controllers more reusable in different contexts.

Peter Bacon Darwin

unread,
Mar 14, 2012, 4:23:56 AM3/14/12
to ang...@googlegroups.com
You can also access the current route with "$route.current" if you inject $route into your controller.
Pete

--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To view this discussion on the web visit https://groups.google.com/d/msg/angular/-/YampgreN1h8J.

Nicholas Retallack

unread,
Mar 14, 2012, 1:29:25 PM3/14/12
to ang...@googlegroups.com
On Wed, Mar 14, 2012 at 1:23 AM, Peter Bacon Darwin <pe...@bacondarwin.com> wrote:
You can also access the current route with "$route.current" if you inject $route into your controller.

At first I couldn't see what that would get me, but then I realized the routes are just regular objects.  I could stow extra values in there and merge them with my $routeParams.  Good work-around =]

Nick R

unread,
Apr 2, 2012, 12:01:28 AM4/2/12
to ang...@googlegroups.com
Alright, I'm currently doing this to great success.  I stuff a lot of values in route.current now, so my controllers can all introspect where they are.  It's allowed me to cut down on my controllers by a lot, so they're super generic and really just correspond to differently structured data, since any data that's structured the same way can use the same controller.

I still think my other feature request would be really nice though.  I put some new comments on my issue about it: https://github.com/angular/angular.js/issues/778

Jeremy Orlow

unread,
Feb 21, 2013, 6:54:40 PM2/21/13
to ang...@googlegroups.com
For what it's worth, I'm finding myself in a similar place to Nick R.  (That's how I found this old thread.)

I have a controller that handles several tabs worth of data that is handled by one controller.  I'd love to have each tab change the path of the url (so they're easily sharable/bookmarkable), but I don't want to have the screen flicker while the same data is loaded by a new instance of the same controller.

Is it by chance now possible to do so?

On Wednesday, June 27, 2012 11:02:20 AM UTC-7, Sim wrote:
Hi Nick,

Running into similar issue with subsections. Could you share some code on how you were able to do this?

Thanks

Jeremy Orlow

unread,
Feb 21, 2013, 6:56:58 PM2/21/13
to ang...@googlegroups.com
On Thu, Feb 21, 2013 at 3:54 PM, Jeremy Orlow <jor...@jorlow.com> wrote:
For what it's worth, I'm finding myself in a similar place to Nick R.  (That's how I found this old thread.)

I have a controller that handles several tabs worth of data that is handled by one controller.  I'd love to have each tab change the path of the url (so they're easily sharable/bookmarkable), but I don't want to have the screen flicker while the same data is loaded by a new instance of the same controller.

Is it by chance now possible to do so?

(Better context below...sorry about that.)


On Tuesday, March 13, 2012 3:54:49 AM UTC-7, Nick R wrote:
I was playing around with $route today and with the reloadOnSearch:false feature and I found it pretty useful.  In fact, I even went so far as to alter my copy of Angular to set reloadOnSearch:false for all routes.  That way I could put a bunch of neat global mode-switching features into the url via $location.search and handle them in the $on '$routeChange' handler on the root controller.  The sort of features I targeted here were fullscreen and other viewing preferences that affected the application no matter what you were looking at.  Implementing them on the root controller kept me from having to touch every controller or every route with this information.

The downside of this is that my urls don't look as good with all those querystring arguments in them.  And that got me thinking -- why can't other routing information work the same way reloadOnSearch does?  What if, if you changed $location.path in such a way that didn't end up changing the current controller, you could have it call $on '$routeChange' with the new routing variables instead of destroying and re-creating the controller?

Another big reason why I started using reloadOnSearch:false is so that my inner scrollable content wouldn't be jumped back to the top every time I wanted to change the url.  For example, if you were scrolling through a sidebar and picking out items that altered the url, it would be frustrating if that sidebar kept scrolling back to the top.  Using querystring arguments here looks even uglier than it does with global features though.


While I'm on the subject of routing, it would be really nice if you could specify some extra parameters to be passed along in the route params for a controller.  The situation I keep getting into is this one:

$route.when('/specific_section/specific_subsection', controller:SpecialController);
$route.when('/specific_section/specific_subsection_2', controller:SpecialController);
$route.when('/:section/:subsection', controller:DefaultController);

Here I am trying to re-use SpecialController for two special cases to my default routing.  Unfortunately, I have no way of knowing which special case was chosen, since it doesn't pass on the section and subsection variables that the default controller does.  If controller inheritance was a thing, I could create two different controllers that both inherited the behavior of SpecialController so I wouldn't have to repeat it.  But currently it seems like SpecialController has to re-parse the url to figure out where it is, or perhaps I have to copy-paste it to create both versions.  This problem could also be solved by allowing regular expression captures in routes, as that would let me restrict when this controller was used but still pass along the information I matched against.


Nicholas Retallack

unread,
Feb 21, 2013, 7:45:37 PM2/21/13
to ang...@googlegroups.com
My final solution was to stop using $route and <ng-view> entirely.

Instead, I do $rootScope.$on "$locationChangeSuccess" and then analyze $location.path myself.  Then I can do whatever I want, and have pretty urls too.

I ended up abandoning controllers also, and controlling my app by changing variables in the root scope based what I pulled out of the url.  However, you could probably still use them, and intelligently reuse their instances.  Or you could straight up recreate their instances all the time, because so long as they end up generating an identical scope each time the $apply step wont even notice the difference.  You could also impersonate the router using $rootScope.$broadcast "$routeUpdate" events that your controllers listen to and use to update their scopes.



On Thu, Feb 21, 2013 at 3:54 PM, Jeremy Orlow <jor...@jorlow.com> wrote:

--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular+u...@googlegroups.com.

To post to this group, send email to ang...@googlegroups.com.

Peter Bacon Darwin

unread,
Feb 22, 2013, 6:26:27 AM2/22/13
to ang...@googlegroups.com

This is not a bad idea!

Pete
...from my mobile.

Richard Zschech

unread,
May 21, 2014, 12:45:04 PM5/21/14
to ang...@googlegroups.com
Hi Nick,

I got around the lack of reloadOnPath:false by doing the following:

$routeProvider.when('/object/:objectId', {...})

When the app want's to change the object id without reloading the controllers set the path params on the current route:

var id = '...';
$route.current.pathParams.objectId = id;
$location.path('/object/' + id);

angular-route checks if the path params change before processing the $routeChangeStart event and instead generates a $routeUpdate event.

I know you've moved away from ng-view, but I thought you might be interested.
Reply all
Reply to author
Forward
0 new messages