AngularJS中的动态路由 - 我可以在设置$ routeProvider之前从服务器检索数据吗?

时间:2013-04-03 06:24:32

标签: angularjs angularjs-routing

在设置$routeProvider上的所有路由之前,有没有办法让服务器点击检索数据?我希望能够根据此远程数据动态设置路由。我试过这样的事情:

angular.module("myApp").config(["$routeProvider", "$http", function($routeProvider, $http) {
    $http.get("myData").success(function(data) {
        $routeProvider.when(data.dynamicRoute, {
            //route definition
        }
        //or
        $routeProvider.when("/known/route", {
            redirectTo: data.dynamicRoute
        }
    });
}]);

但是会导致以下错误:

Unknown provider: $http from myApp

所以,我知道配置功能是注入提供者而不是服务。但是,我仍然想知道我是否可以某种方式实现我的最终目标?我不认为我可以用$httpProvider做到这一点,但如果我错了,请有人纠正我。如果有一些根本原因导致这种情况无法实现,请解释一下。对此有任何帮助将非常感激。

4 个答案:

答案 0 :(得分:7)

这是100%可行的解决方案!

  1. 准备路线。它们可能在json中看起来像这样的

    {"0":{"id":1,"when":"/","controller":"MainController","template":"app/views/site/main_inner.html"},"1":{"id":2,"when":"/firm/:firmID","controller":"CompanyController","template":"app/views/site/firm.html"},"2":{"id":3,"when":"/search","controller":"SearchController","template":"app/views/site/search.html"}}
    
  2. 首先,您必须对RouteProvider进行全局引用

      var $routeProviderReference;
     var app = angular.module('myApp', []);
    
      app.config(['$routeProvider', function($routeProvider) {
      $routeProviderReference = $routeProvider;
      }]);
    
  3. 其次,使用run方法对路由进行ajax调用。

       app.run(['$rootScope', '$http', '$route', function($rootScope, $http, $route) {
        //getting routes
        $http.get('routes.php').success(function (data) {
    
        angular.forEach(data, function (route) {
            $routeProviderReference.when( route.when, { templateUrl: route.template, controller: route.controller } );
        });
        $routeProviderReference.otherwise({ redirectTo: '/' });
        $route.reload();
    
    });
    
    }]);
    
  4. 有关详细信息,请参阅参考文献http://blog.brunoscopelliti.com/how-to-defer-route-definition-in-an-angularjs-web-app

答案 1 :(得分:5)

没有办法做到这一点。

提供商是可配置的服务创建者。它们允许我们提供用于配置其创建的API。可配置性是我们config块的原因。这些是在服务可用之前使用以配置其创建。因此,您可以将设置传递给分别在创建$routeProvider$httpProvider服务时使用的$route$http

由于此阶段的服务仍在配置,因此服务本身无法注入 - 它们实际上并不存在。

$routeProvider允许我们配置路由,这些路由必须在我们的应用程序启动时运行。 在我们的应用程序运行期间,在某个随机点开始路由是没有意义的。

这就是说,在配置完成之前,您无法开始运行应用程序,这就是使用$http的含义。所以没有办法从远程数据定义路由。


对于它的价值,我认为无论如何我都不会看到这种动态路线的价值;它们本质上是不可预测的,因为它们是根据非静态数据构建的。这将彻底打破书签,这是路由的主要目的。

所以我会问你为什么觉得有必要先做这件事,然后退后一步,看看这是否真的应该是理想的做法。

随意发表评论以引发进一步的讨论。

答案 2 :(得分:4)

更新: @ dnc253 - angular-detour现已准备就绪,我认为您可以使用它来获取从json加载的路由。它还没有完整记录,也没有测试,因此从某种意义上说它肯定不完整,但是将json合并到路由器的实时实例中已经有一段时间了。

如果您仍在寻找使用服务器定义路线的方法,可以read instructions on running the samples然后查看第三个样本的mergeJson call in app.js。反馈会很棒 - 我现在开始使用真正的文档/测试,因此没有必要告诉我文档很糟糕而且没有任何测试 - 我就是那个。 :)如果此功能仍在您的需求列表中,希望样本足以发出吱吱声

答案的较早部分:如果您只想要一个由服务器使用JSON定义的静态路由集,您可以使用类似JQuery的东西来获取之前的路由数据 / em>您配置应用程序。

伪代码:

$.ajax({
  url: "http://example.com/routes"
  }
}).done(function ( data ) {
    angular
        .module('myApp',[])
        .config(function($routeProvider) {
          //read routing instructions from data and call "when" on $routeProvider to define the routes
         });

});

这也适用于ui-router。但它只允许您获取一组初始路由,因此虽然它为您提供了数据驱动定义的可能性,但它们仅由客户端加载应用程序时可用的数据驱动。

正如eazel7指出的那样,如果您在配置时创建自己的绑定到提供程序的服务,那么可以在运行时访问提供程序。 然而,要做你想做的事情,你需要离开进程来进行$ http调用,并且使用当前的路由器(库存Angular核心和ui-router)你将无法获得在有人访问您的网站时,如果深层链接失败,请及时填写路由器。此外,这两个路由器都使用函数来填充路由“表”,因此在最初配置之后不会更新路由。

我正在研究解决这些问题的方法,这样如果路由器不知道请求的路由,它将尝试在调用回退路由之前从服务器获取它或失败。还将支持检查已知路由的修改。基本上使用AJAX / JSON接口进行懒惰路由到服务器。它基于ui-router,并且生活在https://github.com/afterglowtech/angular-detour。它目前实现了路由的可编辑性,但我还没有完成懒惰/服务器通信。这是我列表中的下一个。注意它,它应该最终做你想要的。

答案 3 :(得分:2)

我认为最简单的方法是稍后解决路线,例如,你可以通过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();
    });
});