-
Notifications
You must be signed in to change notification settings - Fork 27.4k
$RouteProvider should activate controller, even when no templateUrl or template is passed #1838
Comments
👍 Is there a commonly accepted pattern for solving this perhaps? Something akin to writing your own router? |
@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). |
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? |
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. |
Have you tried putting the code in a resolve handler for the route? On 19 January 2013 20:30, Luis Ramón López [email protected] wrote:
|
But where would I put the listener on $routeChangeSuccess or the resolve handler? In a controller? |
Inside the resolve handler you could change the location if necessary. On 21 January 2013 15:52, Lukas Olson [email protected] wrote:
|
Ah, wasn't aware of resolve handlers. I guess you could put it there. Something like
where RedirectController is the function that actually redirects?? |
Yes something like that but I would not call it a Controller! It will be .when("/", {resolve: {redirect: redirectService}}) On 21 January 2013 18:21, Lukas Olson [email protected] wrote:
|
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. |
Sounds good. Thanks for all your help. |
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? |
Could you post kind of a code snippet of how you're doing it, @leeolayvar? |
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
And this my friends works very well. |
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 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 |
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 |
I would welcome support for this; I too tried to implement a |
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. |
@julianlloyd I dealt with logout before, this is what I did to make it work w/o a controller or template.
|
@buunguyen Awesome, thanks for the idea; here’s my implementation: .when('/logout', {
resolve: {
logout: function ($q, $location, $http) {
var deferred = $q.defer();
$http.post('/logout')
.success(function (data, status, headers, config) {
deferred.reject();
$location.url('/login');
});
return deferred.promise;
}
}
}) With Express handling app.post('/logout', function (req, res) {
req.session.destroy(function (err) {
if (!err) {
res.send(200);
}
});
}); |
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. |
I have understand why people has tolerance about angulajs routing. Someone messes comments. |
@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. |
Yeah this should totally be a thing. Also guys above, I just wanted to note that you should call |
@leeola Thanks for posting about how using a service doesn't work. Saved me tons! |
@cha0s - I think they are calling @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: app.factory('fooService', [$http, function ($http) {
return function() {
return $http(...);
};
}]); Then in your resolve you can do this: $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 .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. |
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.
The text was updated successfully, but these errors were encountered: