【问题标题】:best practice for conditional injection of service into a controller for AngularJS将服务有条件地注入 AngularJS 控制器的最佳实践
【发布时间】:2014-07-10 04:52:44
【问题描述】:

我对 Angular 中的依赖注入有疑问。这个问题的关键是:有没有办法告诉 Angular 不要注入你要求的所有依赖项——这样它就不会抛出错误。我想要这个功能的原因是因为我在常规路线(/addPlayer)和允许用户添加玩家的模式中都使用了控制器。换句话说,我有 addPlayer.html 和它的控制器 addPlayer.js。 我想允许用户也通过模式添加用户。此模式使用 addPlayer.html 和 addPlayer.js。但是,当使用模态时,我需要注入 $modalInstance 。不使用模态时,我不需要注入 $modalInstance。目前,当我访问“/addPlayer”时,我的代码给了我一个错误,因为它说它找不到 $modalInstance。

更多细节:

我有一个页面(/sportsTeams,由 SportsTeamsCtrl 控制),其中包含供用户选择的球员列表。 One of the options is "--- Add New Player ---", which when selected, will tr​​igger a modal opening, allowing the user to add a new player.

我的代码如下所示:

首先,我有一个用于页面 (/sportsTeams) 的控制器,用户可以在其中选择/添加球员。这个控制器有一个启动新模式的选项,它使用我在“ModalsService”中定义的函数。我之所以写 ModalsService 是因为我希望能够从其他各种页面添加玩家,并且我不想一遍又一遍地编写相同的代码。

App.controller('SportsTeamsCtrl', function($scope, ModalsService) {

    $scope.selectOption = function(option) {
       if (option == '--- Add New Player ---') {
           ModalsService.launchPlayerModal().then(function(newOption) {
              $scope.player = newOption;
           }, function(err) {
              console.log(err);
           });
       }
    }
}

然后,我的“ModalsService”看起来像这样:

App.factory('ModalsService', function($modal, $q) {

  var launchPlayerModal = function() {
    var deferred = $q.defer();
    var modalInstance = $modal.open({
      templateUrl: '/partials/addPlayer.html',
      controller: 'AddPlayerCtrl',
      size: 'lg',
      resolve: {
        isModal: function() {return true;}
      }
    });
    modalInstance.result.then(function(selectedPlayer) {
      deferred.resolve(selectedPlayer);
    }, function() {
      deferred.reject();
      console.log('modal dismissed at ' + new Date());
    });
    return deferred.promise;
  };

}

如您所见,ModalsService 中的 'launchPlayerModal' 函数调用了 $modal 提供的 $open 函数。它使用“AddPlayerCtrl”。它返回一个承诺。

现在,这是我遇到问题的地方。在“AddPlayerCtrl”中,我有以下代码

App.controller('AddPlayerCtrl', function($scope, isModal, $modalInstance) {

  $scope.isModal = isModal;

  $scope.addPlayer = function(player) {

      addPlayerToDatabase(category).then(function(data) {

        if ($scope.isModal) {
          $modalInstance.close(data);
        }

      }, function(err) {
        console.log(err);
      });
  };
} 

所以我遇到的问题是因为一个简单的原因:我想使用这个“SportsTeamCtrl”作为模式和常规路由到“/addPlayer”的控制器。基本上,当我的网站转到“/addPlayer”时,我想使用“AddPlayerCtrl”。另外,当我有一个包含用于选择玩家的下拉选项列表的页面并且其中一个选项将启动添加玩家的模式时,我想使用这个相同的“AddPlayerCtrl”。

问题是我只需要在使用模态时注入 $modalInstance 。如果我不使用模态,我不需要注入 $modalInstance。

目前,当我转到“/addPlayer”时,出现以下错误:

Error: [$injector:unpr] Unknown provider: $modalInstanceProvider <- $modalInstance

我明白为什么会出现此错误 - 这是因为当我转到“/addPlayer”时,$modal.open 没有注入 $modalInstance。

所以我的问题是 - 有条件地注入 $modalInstance 或任何服务的最佳方法是什么。

另外,我知道我可能会收到很多回复,说我应该只有两个单独的控制器,一个用于“/addPlayer”路由,一个用于加载“addPlayer”内容的模式。我知道我可以使用控制器继承,但我不确定这是否是最好的方法。

【问题讨论】:

  • 你是怎么解决这个问题的?我有完全一样的问题。我只需要在用作模式时注入 $uibModalInstanceProvider

标签: javascript angularjs


【解决方案1】:

您应该制作 2 个单独的控制器并将共享逻辑推送到服务中。

然后将共享逻辑服务注入两个控制器。

希望这会有所帮助。

【讨论】:

  • 好的,这有帮助。很多......但我不得不问 - 为什么像我想要的那样拥有 1 个控制器不是一个聪明的主意?
  • 通常1个html部分有1个控制器,控制器应该只有绑定/显示数据的逻辑,业务逻辑应该进入服务
  • 所以你是说我有一个单独的“addPlayer.html”用于/addPlayer,另一个“addPlayerModal.html”用于模态?即使它们几乎完全相同?另外,通过业务逻辑,您是什么意思?我为在“AddPlayerCtrl”中将播放器添加到数据库而编写的函数应该被视为业务逻辑吗?
  • 如果是同一个html,你可以把它推到一个指令中,并在addPlayer.html和addPlayerModal.html上加盖印章。是的,您可以将其推送到服务中,然后调用 playerService.addPlayer()。
【解决方案2】:

$injector 可以帮你解决这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-27
    • 1970-01-01
    相关资源
    最近更新 更多