AngularJS动态路由

Gre*_*reg 88 javascript url-routing content-management-system angularjs

我目前有一个内置路由的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: '/' });
  }]);
Run Code Online (Sandbox Code Playgroud)

我的应用程序内置了一个CMS,您可以在/ pages目录中复制和添加新的html文件.

即使对于新的动态添加文件,我仍然希望通过路由提供程序.

在理想的世界中,路由模式将是:

$ routeProvider.when('/ pagename ',{templateUrl:'/ pages/pagename .html',controller:CMSController});

因此,如果我的新页面名称是"contact.html",我希望有角度选择"/ contact"并重定向到"/pages/contact.html".

这有可能吗?!如果是这样的话怎么样?!

更新

我现在在我的路由配置中有这个:

$routeProvider.when('/page/:name', { templateUrl: '/pages/home.html', controller: CMSController })
Run Code Online (Sandbox Code Playgroud)

在我的CMSController中:

function CMSController($scope, $route, $routeParams) {
    $route.current.templateUrl = '/pages/' + $routeParams.name + ".html";
    alert($route.current.templateUrl);
}
CMSController.$inject = ['$scope', '$route', '$routeParams'];
Run Code Online (Sandbox Code Playgroud)

这会将当前templateUrl设置为正确的值.

但是我现在想用新的templateUrl值更改ng-view.这是如何完成的?

Rob*_*zvi 132

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'
        });
    }
]);
Run Code Online (Sandbox Code Playgroud)
  • 添加*可让您动态处理多个级别的目录.示例:/ page/cars/selling/list将捕获此提供程序

从文档(1.3.0):

"如果templateUrl是一个函数,它将使用以下参数调用:

{Array.} - 通过应用当前路由从当前$ location.path()中提取的路由参数"

when(path,route):方法

  • path可以包含以冒号开头并以星号结尾的命名组:例如:name*.当路由匹配时,所有字符都急切地存储在给定名称下的$ routeParams中.

  • 需要与时俱进...我在v1.0.2中缺少的功能现在可用.更新已接受的答案 (5认同)
  • 请解释一下,从'urlattr`设置或发送的地方,我的意思是`urlattr.name`会产生什么? (3认同)

Gre*_*reg 37

好的解决了.

为GitHub添加了解决方案 - http://gregorypratt.github.com/AngularDynamicRouting

在我的app.js路由配置中:

$routeProvider.when('/pages/:name', {
    templateUrl: '/pages/home.html', 
    controller: CMSController 
});
Run Code Online (Sandbox Code Playgroud)

然后在我的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'];
Run Code Online (Sandbox Code Playgroud)

#views是我的 <div id="views" ng-view></div>

所以现在它适用于标准路由和动态路由.

为了测试它,我复制了about.html,称为portfolio.html,更改了它的一些内容并输入/#/pages/portfolio到我的浏览器中,并显示了preyo portfolio.html ....

更新了 添加$ apply和$ compile到html,以便可以注入动态内容.

  • 如果我理解正确的话,这只适用于静态内容.这是因为在通过jQuery(在angular的范围之外)实例化控制器之后,你正在改变DOM.像{{this}}这样的变量可能会起作用(我必须尝试),但指令很可能不会.请注意这一点,因为它现在可能很有用,但可以在以后破解代码. (2认同)
  • 有效,但你不应该在控制器中进行DOM操作. (2认同)

小智 16

我认为最简单的方法是稍后解决路线,例如,你可以通过json询问路线.看看我在配置阶段通过$ provide在$ routeProvider中创建了一个工厂,所以我可以在运行阶段继续使用$ 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();
    });
});
Run Code Online (Sandbox Code Playgroud)

  • @virtualandy,它通常不是一个很好的方法,因为你在不同的阶段提供一个提供者 - 这反过来可以泄漏应该在配置阶段隐藏的高级工具.我的建议是使用UI-Router(处理很多困难),使用"resolve","controllerAs",以及将templateUrl设置为函数等其他功能.我还构建了一个"presolve"模块,我可以共享它可以$插入路由方案的任何部分(模板,templateUrl,控制器等).上述解决方案更优雅 - 但您主要关注的是什么? (2认同)

Tia*_*dão 7

在$ routeProvider URI模式中,您可以指定变量参数,如下所示:$routeProvider.when('/page/:pageNumber' ...,并通过$ routeParams在控制器中访问它.

在$ route页面的末尾有一个很好的例子:http://docs.angularjs.org/api/ng.$ro​​ute

编辑(编辑问题):

不幸的是,路由系统非常有限 - 关于这个主题有很多讨论,并且已经提出了一些解决方案,即通过创建多个命名视图等.但是现在,ngView指令每个路由只提供一个视图,一对一的基础.您可以通过多种方式进行此操作 - 更简单的方法是将视图的模板用作加载器,并<ng-include src="myTemplateUrl"></ng-include>在其中包含标记($ scope.myTemplateUrl将在控制器中创建).

我使用更复杂(但更清晰,更大,更复杂的问题)解决方案,基本上完全跳过$ route服务,详情如下:

http://www.bennadel.com/blog/2420-Mapping-AngularJS-Routes-Onto-URL-Parameters-And-Client-Side-Events.htm


小智 5

不知道为什么这个工作但动态(或者如果你愿意,可以使用通配符)路径可以在角度1.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;
}).
Run Code Online (Sandbox Code Playgroud)

example.com/foo - >加载"foo"partial

example.com/bar->加载"bar"部分

无需在ng-view中进行任何调整.'/:a'的情况是我发现的唯一一个可以实现此变量的变量.'/:foo'不起作用,除非你的部分都是foo1,foo2等...'/:a'适用于任何部分名称.

所有值都会激活动态控制器 - 所以没有"否则",但我认为这是您在动态或通配符路由方案中寻找的东西.