AngularJs: $routeProvider с именем динамического контроллера не загружается

В документации AngularJs говорится, что вы можете указать либо строку, либо функцию для контроллера и templateUrl в объекте маршрута при настройке $routeProvider, однако я сталкиваюсь с проблемой при использовании функции для динамического определения контроллера на основе параметров $location. У меня есть следующая конфигурация маршрута:

$routeProvider
       .when( '/workspace/:workspaceId/product/:productId/item/:itemType/:itemId/edit', {
        templateUrl: function ( param ) {
          switch ( param.itemType ) {
            case 'topic':
              return 'topic.tpl.html';
            case 'course':
              return 'course.tpl.html';
          }
          throw new Error( "Unknown product item type '" + param.itemType + "'" );
        },
        controller: function ( param ) {
          switch ( param.itemType ) {
            case 'topic':
              return 'TopicController';
            case 'course':
              return 'CourseController';
          }
          throw new Error( "Unknown product item type '" + param.itemType + "'" );
        }
      } );

При загрузке приложения получаю следующую ошибку:

Error: [$injector:unpr] Unknown provider: paramProvider <- param

Я пропустил что-нибудь очевидное здесь? Переключение контроллера на использование строки, а не функции, устраняет проблему.

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

Любая помощь будет принята с благодарностью!

Джозеф.


person Joseph Paterson    schedule 10.02.2015    source источник
comment
Откуда берется param и что вы пытаетесь сделать? почему вы не можете создать для них два маршрута вместо динамического маршрута?   -  person yangli-io    schedule 11.02.2015
comment
Я думал, что Angular это предоставил (так же, как и для templateUrl)? Создание двух маршрутов, безусловно, вариант, но я подумал, что могу сделать это и таким образом.   -  person Joseph Paterson    schedule 11.02.2015
comment
Возможно, param означает $routeParams?   -  person JcT    schedule 11.02.2015
comment
Установка его в $routeParams избавляет от ошибки, но указанный контроллер не загружается. Похоже, если вы указываете функцию, то Angular пытается использовать эту функцию в качестве контроллера, а не использовать ее для предоставления имени контроллера.   -  person Joseph Paterson    schedule 11.02.2015
comment
попробуйте добавить () в конце - function (param) { switch (param.itemType) { case 'topic': return 'TopicController'; case 'курс': вернуть 'CourseController'; }()   -  person yangli-io    schedule 11.02.2015
comment
С этим тоже не повезло, я больше не получаю ошибку неизвестного провайдера, но параметр не определен (также пробовал с $ routeParams, и это тоже не определено)   -  person Joseph Paterson    schedule 11.02.2015


Ответы (1)


Я думаю, что часть проблемы может заключаться в том, что когда вы предоставляете контроллеру функцию, а не строку, это не функция, которая должна возвращать имя контроллера, а функция, которая должна вести себя как контроллер.

Взгляните на следующее: поведение маршрута/динамического контроллера, кажется, работает. Я использую $controller для создания экземпляра контроллера по имени. Так что в этом случае я фактически не возвращаю другой контроллер динамически, я создаю экземпляр нового контроллера в анонимном контроллере, который я передал в $routeProvider.

Другой вопрос, является ли это лучшим способом достижения желаемого конечного результата. ;) Довольно популярен проект angular-ui/ui-router.

angular.module('myApp', ['ngRoute'])
  .config(function($routeProvider) {
    $routeProvider
      .when('/workspace/:workspaceId/product/:productId/item/:itemType/:itemId/edit', {
        template: '<h1>{{title}}</h1><p>{{test}}</p>',
        controller: function($scope, $routeParams, $controller) {
          switch ($routeParams.itemType) {
            case 'topic':
              $controller('TopicController', {
                $scope: $scope
              });
              break;
            case 'course':
              $controller('CourseController', {
                $scope: $scope
              });
              break;
          }
        }
      })
      .when('/', {
        template: '<h1>Home</h1><p>{{test}}</p>',
        controller: 'home'
      });
  }).controller('home', function($scope) {
    $scope.test = 'Hello world.';
  }).controller('TopicController', function($scope) {
    $scope.title = "Topic";
    $scope.test = 'Success!';
  }).controller('CourseController', function($scope) {
    $scope.title = "Course";
    $scope.test = 'Success again!';
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular-route.min.js"></script>
<div ng-app="myApp">
  <a href="#/workspace/1/product/1/item/topic/1/edit">Topic</a>
  <a href="#/workspace/1/product/1/item/course/1/edit">Course</a>
  <div ng-view />
</div>

person JcT    schedule 10.02.2015
comment
Я заметил, что мой ответ очень похож на ответ в предоставленной вами ссылке: stackoverflow.com/a/22885416/446030. В комментарии под этим ответом отмечено, что, по-видимому, это может привести к некоторым проблемам с разрешениями, если они вам нужны. Так что, возможно, работа с angular-ui/ui-router даст вам больше необходимой гибкости с меньшим количеством компромиссов. - person JcT; 11.02.2015
comment
Спасибо за ваш подробный ответ! Пока пойду с этим, а также посмотрю на ui-router. - person Joseph Paterson; 11.02.2015