2013-07-08 3 views
23

У меня есть этот кусок разметки 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 в моем основном контроллере?

+0

Хорошо, тогда где вы это определяете? Если модуль не знает, то ...? –

ответ

0

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

  • с $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" достигается (что происходит только один раз, при запуске приложения)

+0

Эй, не могли бы вы показать какой-то код, используя подход «наследовать»? Мне интересно, как вы могли это сделать? – CHAPa

+0

привет @CHAPa, может быть, это поможет: http://stackoverflow.com/questions/18461263/can-an-angularjs-controller-inherit-from-another-contoller-in-the-same-module Я думаю, вы можете иметь контроллер в div выше, чем 'ng-view' –

+0

Наследование контроллера означает наследование наследования? если да, мы могли бы создать внешний контроллер, который находится внутри ng-view. Спасибо Eduard – CHAPa

2

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

То, что я обнаружил, заключается в том, что $ routeParams требуется некоторое время для загрузки в главный контроллер, он, вероятно, сначала инициирует главный контроллер, а затем устанавливает $ routeParams в Child 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); 
    }]); 
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); 

    }); 

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

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

+0

подал вопрос на angularjs github: https://github.com/angular/angular.js/issues/7053 – plong0

4

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

Вы также можете вводить услугу маршрута $, который будет показывать ваши Params немедленно.

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

для меня '$ routeChangeSuccess' не стрелял иногда и' $ route .current.params' спас меня! Спасибо друг! – snippetkid

68

Служба $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 
    }); 
); 
+5

Это должен быть принятый ответ! Благодарю. – adamweeks

+0

Отлично! Очень хорошо написано. –

+0

Я использую stateprovider .. поэтому его никогда не вызывали .. но когда я использую '$ stateChangeSuccess', тогда' r $ outeParams 'все еще пустой объект – Sami

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 
} 

и впрыснуть $ rootScope в вашем IndexCtrl (относится к индексу.html)

.controller('IndexCtrl', function($scope, $rootScope){ 
    // Some code 
}); 
Смежные вопросы