23

我有这段布局html:

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

  <div ng-view></div>

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

现在显然,当我尝试使用$routeParamsin 时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路由匹配的 URL 时/:whatever,为什么只有子控制器能够访问路由参数,而主控制器不能?如何:whatever在主控制器中获取路由参数?

4

6 回答 6

71

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

要在填充时收到通知,$routeParams请订阅$routeChangeSuccess. $scope(如果您在一个无法访问 child 的组件中$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
  });
);
于 2014-07-18T01:42:32.010 回答
4

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

您还可以注入 $route 服务,该服务将立即显示您的参数。

angular.module('MyModule')
  .controller('MainCtrl', function ($scope, $route) {
      console.log('routeParams:'+JSON.stringify($route.current.params));
  });
于 2014-06-21T21:43:15.010 回答
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);
  }]);
于 2013-08-15T20:55:41.130 回答
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 的 20 毫秒延迟甚至不明显,而且少于该延迟似乎会产生不一致的结果。

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

于 2014-04-09T07:31:23.020 回答
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"到达线路时实例化一次(仅在应用程序启动期间发生一次)

于 2013-07-08T06:34:20.810 回答
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
});
于 2016-02-03T09:35:26.020 回答