我正在使用angularjs网站,并且在Rails中使用路由以及在php中使用Laravel。通过Laravel中的路线,我们可以动态创建一组类似于:
的路线 foreach($cities as $city):
Route::get($city.'/hotels');
Route::get($city.'/{slug}');
endforeach;
在这里,我们在Laravel中定义了一系列单独的路线,除了city
和slug
的值之外,技术上看起来一样。
在这种情况下,我发现angularJS在定义路线时有点受限。坦率地说,我有点迷失了。
我在这里做了一些修改 - 基本上我设置了一个服务,它从我的数据库中检索资产,例如在这种情况下的城市和类别列表。我正在尝试这样做:
如果{slug}
位于从我的API检索到的类别数组中,请使用我的ListController
和列表视图,但如果不是,则使用我的SingleVenueController
和单个视图。这是我目前的代码,但它不起作用:(
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;
},
}
})
在上面sharedParams
是一个服务,而getCurrentPageType
只是检查url slug来决定要发回的控制器 - 但它根本不起作用:(
答案 0 :(得分:6)
如何使用参数定义单个路径? 在angularjs v1.x中,您可以使用尽可能多的参数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.
}
})
答案 1 :(得分:2)
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',
});
您可以使用单独的路线进行操作。这个想法是当用户点击主路线时,它首先使用来自后端的数据进行解析。如果满足条件,则解析函数将重定向到特定路由,否则它将不会通过
答案 2 :(得分:2)
Angular中的服务无法在配置阶段注入,因为它们仅在Angular应用程序的 run 阶段可用。
然而,在配置阶段加载$http
服务trick,您可以使用该服务加载城市/类别并设置路线。同时,由于控制器在运行阶段之前尚未注册,因此您可以在配置阶段使用$controllerProvider
预先注册控制器:
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');
...
});
您现在可以调用您的API来获取城市(或其他任何内容)并在注册每条路线时进行迭代:
...
// 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'])
})
}
});
...
请注意,我使用getTemplate
和getController
方法分别使用普通的templateUrl
表达式返回switch
和相关的控制器名称字符串。你可以选择自己的方法。
<强> 注意:的强>
虽然具有templateUrl
路径选项属性的函数可以用于设置自定义模板,但是当您在controller
属性旁边使用函数时,Angular会将其视为控制器的构造函数。因此,在该函数中返回控制器的名称将无法正常工作。
答案 3 :(得分:0)
正如Ahmad已经在他的answer中指出的那样,如果你将函数传递给controller
,它被认为是控制器的构造函数。
此外,您无法在应用程序的配置块中动态注入服务。
所以你可以做的是,将你的sharedData
服务移到单独的应用程序中(在我的代码下面我使用appShared
作为定义此服务的单独应用程序)然后使用angular.injector
。这样您就不必将其定义为templateUrl / controller函数的参数。
顺便说一下,你不能将自定义参数传递给templateUrl函数(参考:https://docs.angularjs.org/api/ngRoute/provider/$routeProvider)
如果templateUrl是一个函数,将使用以下函数调用它 参数:
{Array.<Object>}
- 通过应用当前路线从当前$ location.path()中提取的路线参数
现在,对于控制器,使用$controller
根据您的情况动态加载ListsController
或SingleController
。
加载后,使用angular.extend
扩展当前控制器(由控制器函数定义),以便它继承动态加载控制器的所有属性和方法。
点击此处查看完整代码: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 }));
}
}
});
});