简体   繁体   中英

best practice for conditional injection of service into a controller for AngularJS

I have a question regarding dependency injection in angular. The tldr to this question is: is there a way to tell Angular to not inject all the dependencies you asked for - so that it doesn't throw an error. The reason why I want this functionality is because I'm using a controller for both a regular route (/addPlayer) and a modal that allows users to add players. In other words, I have addPlayer.html and its controller addPlayer.js. I want to allow users to add users also through a modal. This modal uses the addPlayer.html AND the addPlayer.js. However, when using a modal, I need $modalInstance to be injected. When not using modal, I do not need $modalInstance injected. Currently my code gives me an error when I access '/addPlayer' because it says it can't find $modalInstance.

More details:

I have a page (/sportsTeams, controlled by SportsTeamsCtrl) that has a list of players for the user to select. One of the options is "--- Add New Player ---", which when selected, will trigger a modal opening, allowing the user to add a new player.

My code looks something like this:

First, I have a controller for the page (/sportsTeams) where users can select/add players. This controller has an option for launching a new modal, which uses a function that I've defined in the 'ModalsService'. The reason why I have written a ModalsService is because I want to be able to add players from various other pages, and I don't want to write the same code over and over.

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);
           });
       }
    }
}

Then, my 'ModalsService', looks like so:

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;
  };

}

As you can see, the 'launchPlayerModal' function in the ModalsService calls the $open function provided by $modal. It uses the 'AddPlayerCtrl'. It returns a promise.

Now, here is where I am having issues. Within 'AddPlayerCtrl', I have the following code

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);
      });
  };
} 

So the issues I'm having are because of one simple reason: I'd like to use this 'SportsTeamCtrl' as a controller for modals AND regular routes to '/addPlayer'. Basically, when my site goes to '/addPlayer', I'd like to use the 'AddPlayerCtrl'. PLUS, when I have a page that has a list of drop down selections for selecting a player and one of the selections will launch a modal for adding a player, I'd like to use this SAME 'AddPlayerCtrl'.

The problem is that I ONLY need $modalInstance to be injected when I'm using a modal. If I'm not using a modal, I don't need $modalInstance to be injected.

Currently, when I go to '/addPlayer', I get the following error:

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

I understand why I'm getting this error - it's because when I go to '/addPlayer', $modal.open is not injecting $modalInstance.

So my question is this - what's the best way to conditionally inject $modalInstance or any service.

Also, I get that I may get a lot of responses saying I should just have two separate controllers, one for '/addPlayer' routes and one for modals that load 'addPlayer' content. I understand I can use controller inheritance, but I wasn't sure if this was the best way.

You should make 2 separate controllers and push the shared logic into a service.

Then injected the shared logic service into both controllers.

Hope this helps.

$injector can help you with this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM