You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
Repository navigation
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
$RouteProvider should activate controller, even when no templateUrl or template is passed #1838
Sometimes, you don't want to have a template when changing routes. You just want to activate the controller. Currently, it's not possible to do this in Angular.
@lukasolson This sounds really strange to me. Could you elaborate on your use-case?
The thing is that the role of a controller is to set-up a scope for a partial (coming from a template or templateUrl) so data and behavior can be available in a partial. If there is no view there is not much need to setup a scope (there is no one to take advantage of it).
My use case is that I have a route that makes a request to the server and routes to one of two possible routes based on the response. Is there a better way to do this?
Why not just add a small "Loading..." (or empty!) template snippet to the intermediary controller?
But that's changing the view for no reason. The concept is to be able to route something that has no view.
This is mostly just an event (like a click-logout event), but the importance of this is that it is being routed, thus supporting deep linking for the /logout action.
I'm not saying what you suggest will not work, it's just that what you suggest is more of a hack. This specific route has no view, and giving it one is a workaround to a problem.
You could add a listener to the $routeChangeSuccess event (have a look into http://docs.angularjs.org/api/ng.$route). Inside the event handler you should be able to do your magic (i.e. querying the server and changing the path when the promise is returned) if the route matches.
You could add a listener to $routeChangeSuccess events (have a look into http://docs.angularjs.org/api/ng.$route). Inside the event handle you
could (i.e. querying the server and changing the path when the promise is
returned) if the route matches.
—
Reply to this email directly or view it on GitHubhttps://github.com//issues/1838#issuecomment-12460636.
I'm noticing a problem with this method. It seems when you use the resolver as a method to trigger logic (such as a redirect or logout handler), it can only occur once.
If my understanding is right, this is because the service is being loaded so that it can be injected into the controller, but it is only ever loaded once.
This seems like a rather large flaw in this usage.. unless i am doing something wrong. Thoughts?
Well i spent forever trying (and ultimate failing) to get a working example of this on Plunkr/Fiddle (hell, even the ngView Doc Example is broken lol), but i played more with my own code and figured it out!
In my code that was not working, i had roughly this:
and later in my code i defined the service, which was roughly this..
app.factory('fooService', [$http, function ($http) { //do stuff }]);
Well it seems this is the incorrect way to do it? If i ran the resolve like this, my //do stuff code was only executed once. All subsequent url resolves did nothing.
Why did i do it this way? Well, i was looking to keep logic code out of the routing code.
In the end, the solution seems to be to define the function in the route call itself. So, like this:
After seeing these proposed solutions, the original poster's suggestion of allowing template-free controllers still looks cleaner to me. Conditional routing is a common necessity and yet almost no tutorial has dared to share how this has to be done in AngularJS right now.
The argument that a controller's role is to set up scope is a good one, but $scope is an injected dependency. If a controller doesn't need to set up scope, then in the DI frame of mind, we simply don't inject that dependency, right?
Sometimes, you don't want to have a template when changing routes. You just want to activate the controller. Currently, it's not possible to do this in Angular.
What do you meen "sometimes"? I want to do this always. Angular is written by wonderful, charming people. This is not surprising in company, that is fully populated by magestic elves.
Is there a commonly accepted pattern for solving this perhaps
oh lol. pattern driven development.
I dont know why people has tolerance about angulajs routing.
ng-view data will be replaced by provided template (url or string)
I can say that this is the most crappy abstraction that can be found. It's author should be adored and showered with flowers.
@cha0s - I think they are calling reject because they want the route change to fail. But since they are changing the location anyway, I don't think this would make much difference...
@leeola - the reason that your version providing the name of a service to the resolve only worked once is that you are asking the injector to provide a service, which will contain the promise to resolve. Since all services are singletons in Angular, the injector will create this promise on first request but then return the same promise every time afterward. The way to do this better is to define a service that returns a function that will run the request and return a new promise every time it is called:
$routeProvider.when('/foo',{resolve: {foo: ['fooService',function(fooService){fooService();}}// note that we are actually calling the service in the resolve});
which is minification safe.
@jlmakes and @buunguyen - it is worth noting that if you have a promise already, as in the result of calling $http you do not need to provide your own deferred:
.when('/logout',{resolve: {logout: function($location,$http){return$http.post('/logout').then(function(response){$location.url('/login');throw'';// effectively rejects the resolve (but I don't think this is needed)});}}})
I have the same issue, but I'm lazy-loading modules using route resolve.
So I made a service that is helping router to activate the module if the router can't
Activity
leeola commentedon Jan 19, 2013
👍
Is there a commonly accepted pattern for solving this perhaps? Something akin to writing your own router?
pkozlowski-opensource commentedon Jan 19, 2013
@lukasolson This sounds really strange to me. Could you elaborate on your use-case?
The thing is that the role of a controller is to set-up a scope for a partial (coming from a template or templateUrl) so data and behavior can be available in a partial. If there is no view there is not much need to setup a scope (there is no one to take advantage of it).
lukasolson commentedon Jan 19, 2013
See http://stackoverflow.com/questions/14411740/how-to-route-without-a-templateurl/
My use case is that I have a route that makes a request to the server and routes to one of two possible routes based on the response. Is there a better way to do this?
abh commentedon Jan 19, 2013
Why not just add a small "Loading..." (or empty!) template snippet to the intermediary controller?
leeola commentedon Jan 19, 2013
But that's changing the view for no reason. The concept is to be able to route something that has no view.
This is mostly just an event (like a click-logout event), but the importance of this is that it is being routed, thus supporting deep linking for the /logout action.
I'm not saying what you suggest will not work, it's just that what you suggest is more of a hack. This specific route has no view, and giving it one is a workaround to a problem.
lrlopez commentedon Jan 19, 2013
You could add a listener to the $routeChangeSuccess event (have a look into http://docs.angularjs.org/api/ng.$route). Inside the event handler you should be able to do your magic (i.e. querying the server and changing the path when the promise is returned) if the route matches.
petebacondarwin commentedon Jan 20, 2013
Have you tried putting the code in a resolve handler for the route?
On 19 January 2013 20:30, Luis Ramón López notifications@github.com wrote:
lukasolson commentedon Jan 21, 2013
But where would I put the listener on $routeChangeSuccess or the resolve handler? In a controller?
petebacondarwin commentedon Jan 21, 2013
Inside the resolve handler you could change the location if necessary.
These handlers always get run before the template is instantiated.
On 21 January 2013 15:52, Lukas Olson notifications@github.com wrote:
lukasolson commentedon Jan 21, 2013
Ah, wasn't aware of resolve handlers. I guess you could put it there. Something like
where RedirectController is the function that actually redirects??
petebacondarwin commentedon Jan 21, 2013
Yes something like that but I would not call it a Controller! It will be
more of a service.
.when("/", {resolve: {redirect: redirectService}})
On 21 January 2013 18:21, Lukas Olson notifications@github.com wrote:
petebacondarwin commentedon Jan 21, 2013
If you are happy with this then we should close this issue. Let me know if you think it should be reopened for any reason.
lukasolson commentedon Jan 21, 2013
Sounds good. Thanks for all your help.
leeola commentedon Feb 19, 2013
@petebacondarwin @lukasolson
I'm noticing a problem with this method. It seems when you use the resolver as a method to trigger logic (such as a redirect or logout handler), it can only occur once.
If my understanding is right, this is because the service is being loaded so that it can be injected into the controller, but it is only ever loaded once.
This seems like a rather large flaw in this usage.. unless i am doing something wrong. Thoughts?
lukasolson commentedon Feb 21, 2013
Could you post kind of a code snippet of how you're doing it, @leeolayvar?
ThomasDeutsch commentedon Feb 23, 2013
My call: http://localhost:9000/#/?editMode=1
as we all know, this is working:
But this is not:
It seems that in the redirect function, the $routeParams get not injected properly.
And then i found out that i have to use $route instead of $routeParams
oh, i get it... i need to do this:
And this my friends works very well.
leeola commentedon Feb 23, 2013
@lukasolson
Well i spent forever trying (and ultimate failing) to get a working example of this on Plunkr/Fiddle (hell, even the ngView Doc Example is broken lol), but i played more with my own code and figured it out!
In my code that was not working, i had roughly this:
and later in my code i defined the service, which was roughly this..
Well it seems this is the incorrect way to do it? If i ran the resolve like this, my
//do stuffcode was only executed once. All subsequent url resolves did nothing.Why did i do it this way? Well, i was looking to keep logic code out of the routing code.
In the end, the solution seems to be to define the function in the route call itself. So, like this:
I am however a little nervous about injecting
$httpin the resolve handler like that. Is there a way to inject that in a minify-safe way?JustinTArthur commentedon Apr 19, 2013
After seeing these proposed solutions, the original poster's suggestion of allowing template-free controllers still looks cleaner to me. Conditional routing is a common necessity and yet almost no tutorial has dared to share how this has to be done in AngularJS right now.
The argument that a controller's role is to set up scope is a good one, but
$scopeis an injected dependency. If a controller doesn't need to set up scope, then in the DI frame of mind, we simply don't inject that dependency, right?jlmakes commentedon Oct 1, 2013
I would welcome support for this; I too tried to implement a
/logoutroute that executes it's controller with no template…nerdburn commentedon Oct 11, 2013
I'm dealing with this same issue and agree that routes that can point to controllers, without the requirement of a templateUrl would be beneficial.
buunguyen commentedon Oct 11, 2013
@julianlloyd I dealt with logout before, this is what I did to make it work w/o a controller or template.
jlmakes commentedon Oct 25, 2013
@buunguyen Awesome, thanks for the idea; here’s my implementation:
With Express handling
POSTrequests to/logoutas such:andrew-aladev commentedon Feb 3, 2014
What do you meen "sometimes"? I want to do this always. Angular is written by wonderful, charming people. This is not surprising in company, that is fully populated by magestic elves.
oh lol. pattern driven development.
I dont know why people has tolerance about angulajs routing.
I can say that this is the most crappy abstraction that can be found. It's author should be adored and showered with flowers.
andrew-aladev commentedon Feb 3, 2014
I have understand why people has tolerance about angulajs routing. Someone messes comments.
caitp commentedon Feb 3, 2014
@andrew-aladev please don't make statements like "Its author should be killed and thrown out of the window." in the future, okay? That is not how things are done. The framework is open to criticism, but there is no place for mean-spiritedness on the bug tracker.
cha0s commentedon Mar 2, 2014
Yeah this should totally be a thing.
Also guys above, I just wanted to note that you should call
deferred.resolve()instead ofdeferred.reject()if there is no error.btoone commentedon Jul 2, 2015
@leeola Thanks for posting about how using a service doesn't work. Saved me tons!
petebacondarwin commentedon Jul 2, 2015
@cha0s - I think they are calling
rejectbecause they want the route change to fail. But since they are changing the location anyway, I don't think this would make much difference...@leeola - the reason that your version providing the name of a service to the resolve only worked once is that you are asking the injector to provide a service, which will contain the promise to resolve. Since all services are singletons in Angular, the injector will create this promise on first request but then return the same promise every time afterward. The way to do this better is to define a service that returns a function that will run the request and return a new promise every time it is called:
Then in your resolve you can do this:
which is minification safe.
@jlmakes and @buunguyen - it is worth noting that if you have a promise already, as in the result of calling
$httpyou do not need to provide your own deferred:Artur93gev commentedon Mar 21, 2017
I have the same issue, but I'm lazy-loading modules using route resolve.
So I made a service that is helping router to activate the module if the router can't