AngularJSdynamic路由
我目前有一个AngularJS应用程序内置的路由。它的工作原理,一切都很好。
我的app.js文件如下所示:
angular.module('myapp', ['myapp.filters', 'myapp.services', 'myapp.directives']). config(['$routeProvider', function ($routeProvider) { $routeProvider.when('/', { templateUrl: '/pages/home.html', controller: HomeController }); $routeProvider.when('/about', { templateUrl: '/pages/about.html', controller: AboutController }); $routeProvider.when('/privacy', { templateUrl: '/pages/privacy.html', controller: AboutController }); $routeProvider.when('/terms', { templateUrl: '/pages/terms.html', controller: AboutController }); $routeProvider.otherwise({ redirectTo: '/' }); }]);
我的应用程序内置了一个CMS,您可以在/ pages目录中复制和添加新的html文件。
即使对于新的dynamic添加的文件,我仍想通过路由提供程序。
在理想的世界中,路由模式将是:
$ routeProvider.when('/ pagename ',{templateUrl:'/ pages / pagename .html',controller:CMSController});
所以如果我的新网页名称是“contact.html”,我想angular拿起“/ contact”,并redirect到“/pages/contact.html”。
这甚至有可能吗? 如果是的话,怎么样?!
更新
我现在有这个在我的路由configuration:
$routeProvider.when('/page/:name', { templateUrl: '/pages/home.html', controller: CMSController })
并在我的CMSController:
function CMSController($scope, $route, $routeParams) { $route.current.templateUrl = '/pages/' + $routeParams.name + ".html"; alert($route.current.templateUrl); } CMSController.$inject = ['$scope', '$route', '$routeParams'];
这将当前的templateUrl设置为正确的值。
但是现在我想用新的templateUrl值来改变ng-view 。 这是如何完成的?
angular.module('myapp', ['myapp.filters', 'myapp.services', 'myapp.directives']). config(['$routeProvider', function($routeProvider) { $routeProvider.when('/page/:name*', { templateUrl: function(urlattr){ return '/pages/' + urlattr.name + '.html'; }, controller: 'CMSController' }); } ]);
- 添加*让您可以dynamic地处理多级目录 。 例如: / page / cars / selling / list将被捕获到这个提供者
从文档(1.3.0):
“如果templateUrl是一个函数,它将被调用以下参数:
{Array。} – 通过应用当前路由从当前$ location.path()提取路由参数“
也
何时(path,路线):方法
- path可以包含以冒号开始并以星号结尾的命名组:例如:name *。 当路由匹配时,所有的字符都被急切地存储在$ routeParams中。
好的解决了它。
将解决scheme添加到GitHub – http://gregorypratt.github.com/AngularDynamicRouting
在我的app.js路由configuration中:
$routeProvider.when('/pages/:name', { templateUrl: '/pages/home.html', controller: CMSController });
然后在我的CMS控制器中:
function CMSController($scope, $route, $routeParams) { $route.current.templateUrl = '/pages/' + $routeParams.name + ".html"; $.get($route.current.templateUrl, function (data) { $scope.$apply(function () { $('#views').html($compile(data)($scope)); }); }); ... } CMSController.$inject = ['$scope', '$route', '$routeParams'];
#views是我的<div id="views" ng-view></div>
所以现在它可以与标准路由和dynamic路由一起工作。
testing它,我复制about.html称为portfolio.html,改变了它的一些内容,并进入/#/pages/portfolio
到我的浏览器,嘿presto portfolio.html显示….
更新已 添加$应用和$编译到HTML,以便可以注入dynamic内容。
我认为最简单的方法就是稍后解决路由问题,例如,可以通过json询问路由。 看看我在$ configProvider期间通过$ provide创build了一个工厂,所以我可以在运行阶段继续使用$ routeProvider对象,甚至在控制器中。
'use strict'; angular.module('myapp', []).config(function($provide, $routeProvider) { $provide.factory('$routeProvider', function () { return $routeProvider; }); }).run(function($routeProvider, $http) { $routeProvider.when('/', { templateUrl: 'views/main.html', controller: 'MainCtrl' }).otherwise({ redirectTo: '/' }); $http.get('/dynamic-routes.json').success(function(data) { $routeProvider.when('/', { templateUrl: 'views/main.html', controller: 'MainCtrl' }); // you might need to call $route.reload() if the route changed $route.reload(); }); });
在$ routeProvider URI模式中,您可以指定variables参数,例如: $routeProvider.when('/page/:pageNumber' ...
,并通过$ routeParams在您的控制器中访问它。
在$ route页面的末尾有个很好的例子: http : //docs.angularjs.org/api/ng.$route
编辑(编辑的问题):
路由系统不幸的是非常有限 – 关于这个主题有很多讨论,并且已经提出了一些解决scheme,即通过创build多个命名视图等。但是现在,ngView指令每个路由只服务一个视图,on一对一的基础。 你可以通过多种方式来解决这个问题 – 最简单的方法就是使用视图的模板作为加载器,并在其中添加一个<ng-include src="myTemplateUrl"></ng-include>
标记($ scope.myTemplateUrl在控制器中创build)。
我使用更复杂的(但更清洁,更大,更复杂的问题)解决scheme,基本上完全跳过$ route服务,这里详细说明:
不知道为什么这个工程,但dynamic(或通配符,如果你喜欢)路线可能在angular1.2.0-rc.2 …
http://code.angularjs.org/1.2.0-rc.2/angular.min.js http://code.angularjs.org/1.2.0-rc.2/angular-route.min.js angular.module('yadda', [ 'ngRoute' ]). config(function ($routeProvider, $locationProvider) { $routeProvider. when('/:a', { template: '<div ng-include="templateUrl">Loading...</div>', controller: 'DynamicController' }). controller('DynamicController', function ($scope, $routeParams) { console.log($routeParams); $scope.templateUrl = 'partials/' + $routeParams.a; }).
example.com/foo – >加载“foo”部分
example.com/bar->加载“bar”部分
在ng-view中不需要任何调整。 '/:a'的情况是我发现的唯一variables将实现这个..'/:foo'不工作,除非你的部分都是foo1,foo2等…'/:一个'任何部分名称。
所有的值激发dynamic控制器 – 所以没有“其他”,但是,我认为这是你在dynamic或通配符路由场景中寻找的东西。
从AngularJS 1.1.3开始,您现在可以使用新的catch-all参数来完成您想要的function。
https://github.com/angular/angular.js/commit/7eafbb98c64c0dc079d7d3ec589f1270b7f6fea5
从承诺:
这允许routeProvider接受匹配子string的参数,即使它们包含斜杠(如果前缀为星号而不是冒号)。 例如,像
edit/color/:color/largecode/*largecode
将会匹配这样的http://appdomain.com/edit/color/brown/largecode/code/with/slashs
。
我已经testing了自己(使用1.1.5),它很好。 只要记住,每个新的URL将重新加载您的控制器,所以为了保持任何forms的状态,您可能需要使用自定义服务。
这是另一个可行的解决scheme。
(function() { 'use strict'; angular.module('cms').config(route); route.$inject = ['$routeProvider']; function route($routeProvider) { $routeProvider .when('/:section', { templateUrl: buildPath }) .when('/:section/:page', { templateUrl: buildPath }) .when('/:section/:page/:task', { templateUrl: buildPath }); } function buildPath(path) { var layout = 'layout'; angular.forEach(path, function(value) { value = value.charAt(0).toUpperCase() + value.substring(1); layout += value; }); layout += '.tpl'; return 'client/app/layouts/' + layout; } })();