$ routeParams在主控制器中为空

时间:2013-07-08 05:53:33

标签: angularjs

我有这个布局html:

<body ng-controller="MainController">
  <div id="terminal"></div>

  <div ng-view></div>

  <!-- including scripts -->
</body>

现在显然,当我尝试在$routeParams中使用MainController时,它总是空的。重要的是要注意MainController应该在每个可能的路线中生效;因此我没有在我的app.js中定义它。我的意思是,我不是在这里定义它:

$routeProvider.when("/view1", {
  templateUrl: "partials/partial1.html"
  controller: "MyCtrl1"
})

$routeProvider.when("/view2", {
  templateUrl: "partials/partial2.html"
  controller: "MyCtrl2"
})

// I'm not defining MainController here!!

事实上,我认为我的问题与此问题完全相同:https://groups.google.com/forum/#!topic/angular/ib2wHQozeNE

但是,我仍然没有得到如何在我的主控制器中获取路由参数......

编辑:

我的意思是我没有将我的MainController与任何特定路线相关联。它的定义;它是所有其他控制器的父控制器。我想知道的是,当你转到/whatever之类的网址时,它与/:whatever这样的路由匹配,为什么只有子控制器才能访问该路由参数,而主控制器不是?如何在主控制器中获取:whatever路由参数?

6 个答案:

答案 0 :(得分:71)

$routeParams服务是异步填充的。这意味着它首次在控制器中使用时通常显示为空。

要在填充$routeParams时收到通知,请订阅$routeChangeSuccess上的$scope事件。 (如果您所在的组件无法访问孩子$scope,例如服务或工厂,则可以注入并使用$rootScope。)

module.controller('FooCtrl', function($scope, $routeParams) {
  $scope.$on('$routeChangeSuccess', function() {
    // $routeParams should be populated here
  });
);

路由使用的控制器或路由包含的模板内的控制器可以立即访问完全填充的$routeParams,因为ng-view在继续之前等待$routeChangeSuccess事件。 (它等待,因为它需要路由信息才能决定哪个模板/控制器甚至可以加载。)

如果您知道您的控制器将在ng-view内使用,则无需等待路由事件。如果你知道你的控制器不会,你会的。如果你不确定,你必须明确允许这两种可能性。订阅$routeChangeSuccess是不够的;只有在$routeParams尚未填充时才会看到该事件:

module.controller('FooCtrl', function($scope, $routeParams) {
  // $routeParams will already be populated
  // here if this controller is used within ng-view

  $scope.$on('$routeChangeSuccess', function() {
    // $routeParams will be populated here if
    // this controller is used outside ng-view
  });
);

答案 1 :(得分:4)

作为plong0提到的$ timeout的替代...

你也可以注入$ route服务,它会立即显示你的参数。

angular.module('MyModule')
  .controller('MainCtrl', function ($scope, $route) {
      console.log('routeParams:'+JSON.stringify($route.current.params));
  });

答案 2 :(得分:2)

我有同样的问题。

我发现$ routeParams需要一些时间才能在主控制器中加载,它可能首先启动主控制器,然后在子控制器上设置$ routeParams。我做了一个解决方法,它在主控制器$ scope中创建一个方法,并在子控制器中通过它传递$ routeParams:

angular.module('MyModule')
  .controller('MainController', ["$scope", function ($scope) {
    $scope.parentMethod = function($routeParams) {
     //do stuff
    }
  }]);

angular.module('MyModule')
  .controller('MyCtrl1', ["$scope", function ($scope) {
    $scope.parentMethod($routeParams);
  }]);

angular.module('MyModule')
  .controller('MyCtrl2', ["$scope", function ($scope) {
    $scope.parentMethod($routeParams);
  }]);

答案 3 :(得分:1)

遇到了同样的问题,并且在他的回答中提到安德烈提到的关于$ routeParams花了一些时间在主控制器中加载的东西,我只是把它放在我的MainCtrl中的超时。

angular.module('MyModule')
  .controller('MainCtrl', function ($scope, $routeParams, $timeout) {

    $timeout(function(){
      // do stuff with $routeParams
      console.log('routeParams:'+JSON.stringify($routeParams));
    }, 20);

  });

使用$ routeParams的20ms延迟甚至不明显,并且不到这似乎有不一致的结果。

更具体地说我的问题,我很困惑,因为我有完全相同的设置使用不同的项目结构(哟cg-angular),当我重建我的项目(yo angular-fullstack)时,我开始遇到问题。 / p>

答案 4 :(得分:0)

这里至少有两个问题:

  • 使用$routeParams获取您未定义的路线参数

  • 定义主控制器的文件并不重要。重要的是在哪个模块/功能

参数必须使用$routeProvider定义,语法为:paramName

$routeProvider.when("/view2/name1/:a/name2/:b"

然后您可以使用$routeParams.paramName检索它们。

您还可以使用查询参数,例如index.html?k1=v1&k2=v2

app.js是您通常定义依赖关系和配置的文件(这就是为什么你有app模块.config块),它包含应用程序模块:

var myapp = angular.module(...);

此模块可以将其他模块作为依赖项(如指令或服务)或每个功能的模块。 一种简单的方法是使用一个模块来封装控制器。接近原始代码的方法是在主模块中至少放置一个控制器:

myapp.controller('MainCtrl', function ($scope) {...}

也许您将控制器定义为全局函数? function MainCtrl() {...}?这会污染全局命名空间。避免它。

在主模块中定义控制器不会使其“在所有路径中生效”。这必须用$routeProvider定义,或者使每个路由的控制器从主控制器“继承”。这样,每条路径的控制器在路径改变后实例化,而主控制器仅在到达行ng-controller="MainCtrl"时实例化一次(在应用期间仅发生一次)启动)

答案 5 :(得分:0)

您只需将定义到控制器中的$ routeParams值传递到$ rootScope

即可
.controller('MainCtrl', function ($scope, $routeParams, MainFactory, $rootScope) {
    $scope.contents = MainFactory.getThing($routeParams.id);
    $rootScope.total = MainFactory.getMax(); // Send total to the rootScope
}

并在IndexCtrl中注入$ rootScope(与index.html相关)

.controller('IndexCtrl', function($scope, $rootScope){
    // Some code
});