$ routeParams пуст в основном контроллере

У меня есть эта часть макета html:

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

  <div ng-view></div>

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

Теперь, по-видимому, когда я пытаюсь использовать $routeParams в MainController, он всегда пуст. Важно отметить, что MainController предполагается действовать во всех возможных маршрутах; поэтому я не определяю его в своем приложении. Я имею в виду, я не определяю его здесь:

$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

Однако, я до сих пор не понимаю, как получить параметры маршрута в моем основном контроллере...

EDIT:

Я имел в виду, что я не связываю свой MainController с каким-либо конкретным маршрутом. Он определил; и это родительский контроллер всех других контроллеров. Я пытаюсь понять, что когда вы переходите к URL-адресу типа /whatever, который сопоставляется с маршрутом, например /:whatever, почему он может получить доступ к параметру маршрута, основного контроллера нет? Как получить параметр маршрута :whatever в моем основном контроллере?

Ответ 1

Служба $routeParams заполняется асинхронно. Это означает, что он обычно будет пустым при первом использовании в контроллере.

Чтобы получать уведомление о заполнении $routeParams, подпишитесь на событие $routeChangeSuccess на $scope. (Если вы находитесь в компоненте, который не имеет доступа к дочернему элементу $scope, например, службе или factory, вы можете вводить и использовать $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
  });
);

Ответ 2

В качестве альтернативы $timeout, о котором упоминалось plong0...

Вы также можете ввести услугу $route, которая немедленно покажет ваши параметры.

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

Ответ 3

У меня та же проблема.

Что я обнаружил, так это то, что $routeParams занимает некоторое время для загрузки в главный контроллер, возможно, сначала инициирует главный контроллер, а затем устанавливает $routeParams в Child Controller. Я сделал обходной путь для создания метода в области Main Controller $и передал через него $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);
  }]);

Ответ 4

была та же проблема, и, построив то, о чем Андре упомянул в своем ответе о $routeParams, на мгновение, чтобы загрузить в главный контроллер, я просто помещал его в тайм-аут внутри моего MainCtrl.

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

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

  });

Задержка в 20 мс для использования $routeParams даже не заметна, и меньше, чем кажется, имеет несогласованные результаты.

В частности, о моей проблеме, я был смущен, потому что у меня была такая же настройка, которая работала с другой структурой проекта (yo cg- angular), и когда я перестроил свой проект (yo angular -fullstack), я начал испытывать проблема.

Ответ 5

У вас есть как минимум две проблемы:

  • с $routeParams вы получаете параметры маршрута, которые вы не определили

  • Файл, в котором вы определяете главный контроллер, не имеет большого значения. важно, в каком модуле/функции

Параметры должны быть определены с помощью $routeProvider с синтаксисом :paramName:

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

а затем вы можете получить их с помощью $routeParams.paramName.

Вы также можете использовать параметры запроса, например index.html?k1=v1&k2=v2.

app.js - это файл, в котором вы обычно определяете зависимости и конфигурацию (почему у вас есть модуль приложения .config), и он содержит модуль приложения:

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

Этот модуль может иметь другие модули в качестве зависимостей, такие как директивы или службы, или модуль для каждой функции. Простым подходом является наличие модуля для инкапсуляции контроллеров. Подход ближе к вашему исходному коду заключается в том, что по крайней мере один контроллер находится в основном модуле:

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

Может быть, вы определили контроллер как глобальную функцию? function MainCtrl() {...}? Это загрязняет глобальное пространство имен. избегайте этого.

Определение вашего контроллера в основном модуле не заставит его "вступать в силу во всех маршрутах". Это нужно определить с помощью $routeProvider или сделать контроллер каждого маршрута "наследованием" от основного контроллера. Таким образом, контроллер каждого маршрута создается после изменения маршрута, тогда как главный контроллер создается только один раз, когда достигается линия ng-controller="MainCtrl" (что происходит только один раз, во время запуска приложения)

Ответ 6

Вы можете просто передать значения $routeParams, определенные в ваш контроллер, в $rootScope

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

и введите $rootScope в свой IndexCtrl (связанный с index.html)

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