admin管理员组文章数量:1287581
I'm working with an angularjs site and have a background with working with routes in Rails and also Laravel in php. With routes in Laravel we could dynamically create a set of routes similar to:
foreach($cities as $city):
Route::get($city.'/hotels');
Route::get($city.'/{slug}');
endforeach;
Here we defined series of seperate routes in Laravel which technically do look the same except for the value of city
and slug
.
I'm finding angularJS a bit limited in defining routes in this case. Frankly am a bit lost here.
UPDATE
I've made some modifications here - basically I set up a service which retrieves assets from my database such as in this case a list of cities and categories. I'm trying to do this:
If {slug}
is in the array of categories retrieved from my API, then use my ListController
and list view but if its not then instead use my SingleVenueController
and single view. Here's my code at the moment but its not working :(
appRouteProvider.when('/:city/:slug', {
templateUrl : function(sharedParams, $routeParams){
t = sharedParams.getCurrentPageType($routeParams);
if(t=='list'){
return '../../app/templates/list.html';
}
if(t=='single'){
return '../../app/templates/single.html';
}
},
controller : function(sharedParams, $routeParams){
t = sharedParams.getCurrentPageType($routeParams);
if(t=='list'){
return 'ListsController';
}
if(t=='single'){
return 'SingleController';
}
},
resolve:{
sharedParamsData:function(sharedParams){
return sharedParams.promise;
},
}
})
In the above sharedParams
is a service and the getCurrentPageType
just checks the url slug to decide what controller to send back - but its not really working at all :(
I'm working with an angularjs site and have a background with working with routes in Rails and also Laravel in php. With routes in Laravel we could dynamically create a set of routes similar to:
foreach($cities as $city):
Route::get($city.'/hotels');
Route::get($city.'/{slug}');
endforeach;
Here we defined series of seperate routes in Laravel which technically do look the same except for the value of city
and slug
.
I'm finding angularJS a bit limited in defining routes in this case. Frankly am a bit lost here.
UPDATE
I've made some modifications here - basically I set up a service which retrieves assets from my database such as in this case a list of cities and categories. I'm trying to do this:
If {slug}
is in the array of categories retrieved from my API, then use my ListController
and list view but if its not then instead use my SingleVenueController
and single view. Here's my code at the moment but its not working :(
appRouteProvider.when('/:city/:slug', {
templateUrl : function(sharedParams, $routeParams){
t = sharedParams.getCurrentPageType($routeParams);
if(t=='list'){
return '../../app/templates/list.html';
}
if(t=='single'){
return '../../app/templates/single.html';
}
},
controller : function(sharedParams, $routeParams){
t = sharedParams.getCurrentPageType($routeParams);
if(t=='list'){
return 'ListsController';
}
if(t=='single'){
return 'SingleController';
}
},
resolve:{
sharedParamsData:function(sharedParams){
return sharedParams.promise;
},
}
})
In the above sharedParams
is a service and the getCurrentPageType
just checks the url slug to decide what controller to send back - but its not really working at all :(
-
Are you using
ui-router
orng-route
? – Merlin Commented Sep 27, 2016 at 14:54 - 1 well, you can insert a service on config, and then, retrieve the list and maps city by city – Joao Polo Commented Sep 27, 2016 at 14:55
- ng-route for now - I'm interested in your solution on using a service how do I do that? – Ali Commented Sep 27, 2016 at 15:16
- I've made amendments to my code - but its not really working right. Can you please give me an idea here? – Ali Commented Oct 5, 2016 at 14:07
- Are you getting errors? – John Roca Commented Oct 12, 2016 at 3:22
4 Answers
Reset to default 6How about defining a single route with a paramater ? In angularjs v1.x you can defined as many routes you want with as many params xor query
.config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/city/:slug', {
templateUrl: 'book.html',
controller: 'BookController',
resolve: {
// you can also retrieve some data as a resolved promise inside your route for better performance.
}
})
ref: https://docs.angularjs/api/ngRoute/service/$route
appRouteProvider.when('/:city/:slug', {
templateUrl : 'dafault.html',
controller : 'DefaultController',
resolve:{
factory: function($routeParams, $http, $location, sharedParams){
var city = $routeParams.city;
var slug = $routeParams.slug;
var deferred = $q.defer();
sharedParams.getCurrentPageType($routeParams).then(function(t) {
if(t=='list'){
$location.path('/' + city + '/' + slug + '/list');
deferred.resolve();
}
else if(t=='single'){
$location.path('/' + city + '/' + slug + '/single');
deferred.resolve();
} else {
deferred.reject();
}
});
return deferred.promise;
},
}
});
appRouteProvider.when('/:city/:slug/list', {
templateUrl: '../../app/templates/list.html',
controller: 'ListsController',
});
appRouteProvider.when('/:city/:slug/single', {
templateUrl: '../../app/templates/single.html',
controller: 'SingleController',
});
You can do it with separate routes. The idea is when user hits the main route it resolves first with the data from the backend. If the condition is met, resolve function will redirect to specific route if not it wont pass
Services in Angular cannot be injected in the configuration phase since they bee available only in the run phase of an Angular application.
There is however a trick to load $http
service in the config phase which you can use to load your cities/categories and set up your routes. Meanwhile, since controllers aren't registered up until the run phase, you may use the $controllerProvider
to register your controllers beforehand in the configuration phase:
app.config(function ($routeProvider, $controllerProvider) {
$controllerProvider.register('ListController', ListController);
$controllerProvider.register('SingleController', SingleController);
// wire the $http service
var initInjector = angular.injector(['ng']);
var $http = initInjector.get('$http');
...
});
You can now call your API to get the cities (or whatever else) and iterate while registering each route:
...
// fetch the cities from the server
$http.get('/cities')
.then(function (response) {
var cities = response.data;
for(var i = 0; i < cities.length; i++){
$routeProvider
// assuming each city object has a `name` property
.when('/' + cities[i]['name'] + '/:slug', {
templateUrl: getTemplate(cities[i]['name']),
controller: getController(cities[i]['name'])
})
}
});
...
Note that I'm using the getTemplate
and the getController
methods which return the templateUrl
and the relevant controller name strings respectively using an ordinary switch
expression. You can choose your own approach.
Plunkr Demo
Note:
While a function with the templateUrl
route options property does work with setting up a custom template, but when you use a function alongside the controller
property, Angular will consider it as the constructor for the controller. Therefore, returning the name of the controller in that function won't work.
As Ahmad has already pointed out in his answer, if you pass a function to controller
it is considered as a constructor for the controller.
Also you can't get a service injected dynamically in config block of your app.
So what you can do is, move your sharedData
service in separate app (in my code below I've used appShared
as a separate app where this service is defined) and then access it using angular.injector
. This way you don't have to define it as a parameter to templateUrl / controller functions.
Btw, you can't pass custom parameters to templateUrl function (ref: https://docs.angularjs/api/ngRoute/provider/$routeProvider)
If templateUrl is a function, it will be called with the following parameters:
{Array.<Object>}
- route parameters extracted from the current $location.path() by applying the current route
Now for the controller, use $controller
to dynamically load either ListsController
or SingleController
based on your condition.
Once that is loaded, extend your current controller (defined by your controller function) using angular.extend
so that it inherits all the properties and methods of the dynamically loaded controller.
Check the plete code here: http://plnkr.co/edit/ORB4iXwmxgGGJW6wQDy9
app.config(function ($routeProvider) {
var initInjector = angular.injector(['appShared']);
var sharedParams = initInjector.get('sharedParams');
$routeProvider
.when('/:city/:slug', {
templateUrl: function ($routeParams) {
console.log("template url - ");
console.log($routeParams);
var t = sharedParams.getCurrentPageType($routeParams);
console.log(t);
if (t == 'list') {
return 'list.html';
}
if (t == 'single') {
return 'single.html';
}
},
controller: function ($routeParams, $controller, $scope) {
//getController(cities[i]['name'])
console.log("controller - ");
console.log($routeParams);
var t = sharedParams.getCurrentPageType($routeParams);
console.log(t);
if (t == 'list') {
angular.extend(this, $controller('ListsController', { $scope: $scope }));
}
if (t == 'single') {
angular.extend(this, $controller('SingleController', { $scope: $scope }));
}
}
});
});
本文标签: javascriptDynamic partial arguments in AngularJS routingStack Overflow
版权声明:本文标题:javascript - Dynamic partial arguments in AngularJS routing - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741238968a2363586.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论