34

following angular.ui Modal example shows the modalInstance calling a ModalIntanceCtrl which is later created as a function:

var ModalDemoCtrl = function ($scope, $modal, $log) {

  $scope.items = ['item1', 'item2', 'item3'];

  $scope.open = function () {

    var modalInstance = $modal.open({
      templateUrl: 'myModalContent.html',
      controller: ModalInstanceCtrl,
      resolve: {
        items: function () {
          return $scope.items;
        }
      }
    });

    modalInstance.result.then(function (selectedItem) {
      $scope.selected = selectedItem;
    }, function () {
      $log.info('Modal dismissed at: ' + new Date());
    });
  };
};

var ModalInstanceCtrl = function ($scope, $modalInstance, items) {

  $scope.items = items;
  $scope.selected = {
    item: $scope.items[0]
  };

  $scope.ok = function () {
    $modalInstance.close($scope.selected.item);
  };

  $scope.cancel = function () {
    $modalInstance.dismiss('cancel');
  };
};

I have a 2 questions/problems:

  1. the docs recommend creating a controller in another way (due to minification issues) for example:

    myApp.controller('GreetingCtrl', ['$scope', function($scope) { $scope.greeting = 'Hola!'; }]);

But if I create the controller like this, how could I Inject it into the modalInstance?

  1. The controller I call here isn't a Modal Instance controller but my global loginCtrl, is this a problem? should I subclass somehow the loginCtrl or call it from the ModalInstanceCtrl? and if so - how exactly?

I'll be glad for guidance and clarfication about this. Thanks!

alonisser
  • 11,542
  • 21
  • 85
  • 139

4 Answers4

31

You question is not very clear, but if you declare controller using the module API, then you can provide the controller to the modal service as a string

myApp.controller('ModalInstanceCtrl', ['$scope', function($scope) { $scope.greeting = 'Hola!'; }]);

controller: 'ModalInstanceCtrl',

The same can be done for loginCtrl if you want to use that in the modal service.

Chandermani
  • 42,589
  • 12
  • 85
  • 88
  • 5
    If you have the `resolve: { someVariableToResolve : function () {} }` in the modal options, you need to actually put that variable into the `['$scope', 'someVariableToResolve', function ($scope, someVariableToResolve){}]`, just an FYI – Callum Linington Oct 07 '14 at 15:12
  • I have a factory 'Myservice' created with a function which makes an ajax request. How do I use this factory function inside ModalInstanceCtrl. Along with that I have some variables to resolve also. like below. current code app.controller('ModalInstanceCtrl', function ($scope, $uibModalInstance, appointmentId, locations){ }); expecting app.controller('ModalInstanceCtrl',['$scope','$uibModalInstance','Myservice', function ($scope, $uibModalInstance, id, items){ }]); – Pradeep Aug 19 '16 at 05:51
12

I have created this plunker for those of you like myself, who like to see an example. It shows how to create a modal without polluting the global namespace. Hopefully it is helpful.

Edited to include code example as per bummi's comment below

index.html

<html ng-app="app">
  <head>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.js"></script>
    <script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.10.0.js">    </script>
<script src="app.js"></script>
    <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css"     rel="stylesheet">
  </head>
  <body>

<div ng-controller="appController">
    <script type="text/ng-template" id="myModalContent.html">
    <div class="modal-header">
        <h3>I'm a modal!</h3>
    </div>
    <div class="modal-body">
        <span>Message:{{message}}</span>
        <ul>
            <li ng-repeat="item in items">
                <a ng-click="selected.item = item">{{ item }}</a>
            </li>
        </ul>
        Selected: <b>{{ selected.item }}</b>
    </div>
    <div class="modal-footer">
        <button class="btn btn-primary" ng-click="ok()">OK</button>
        <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
    </div>
</script>

<button class="btn btn-default" ng-click="showModal()">Open me!</button>
<div ng-show="selected">Selection from a modal: {{ selected }}</div>
</div>
  </body>
</html>

app.js

angular.module('app', ['ui.bootstrap']).
service('DataService', ['$rootScope',
  function($rootScope) {
    this.data = {};
    this.data.message = 'This is a message from a service';
    this.data.items = ['item1', 'item2', 'item3'];
  }
]).
controller('myModal', ['$scope', '$modalInstance', 'DataService',
  function($scope, $modalInstance, dataService) {
    $scope.data = dataService.data;
    $scope.message = dataService.data.message;
    $scope.items = dataService.data.items;

    $scope.selected = {
      item: $scope.items[0]
    };

    $scope.ok = function() {
      $modalInstance.close($scope.selected.item);
    };

    $scope.cancel = function() {
      $modalInstance.dismiss('cancel');
    };

  }
]).
controller('appController', ['$scope', '$modal', '$log', 'DataService',
  function($scope, $modal, $log, dataService) {

    $scope.data = dataService.data;

    $scope.showModal = function() {
      var modalInstance = $modal.open({
        templateUrl: 'myModalContent.html',
        controller: 'myModal'
      });

      modalInstance.result.then(function(selectedItem) {
        $scope.selected = selectedItem;
      }, function() {
        $log.info('Modal dismissed at: ' + new Date());
      });

    };

  }
]);
Community
  • 1
  • 1
Mikt25
  • 695
  • 1
  • 9
  • 18
  • While this link may answer the question, it is better to include the essential parts of the answer [here](http://meta.stackexchange.com/a/8259) and provide the link for reference. Link-only answers can become invalid if the linked page changes. – bummi Apr 08 '14 at 15:38
  • Nice example! It helped me a lot! – Anastasios Andronidis May 26 '14 at 21:37
4

Had a similar issue and declared the modal controller without adding it to the module, like this:

var ModalInstanceCtrl = ['$scope', '$modalInstance', 'items', function ($scope, $modalInstance, items) { ... }

With no other changes required this syntax works with minification as well.

Mark Meyerovich
  • 193
  • 3
  • 9
3

The simple way to do this is use $inject:


    // inject the controller with the following dependencies
    ModalInstanceCtrl.$inject = ['$scope', '$modalInstance', 'items'];

Change the controller method to a named function :


    function ModalInstanceCtrl($scope, $modalInstance, items) {
        $scope.items = items;
        $scope.selected = {
            item: $scope.items[0]
        };

        $scope.ok = function () {
            $modalInstance.close($scope.selected.item);
        };

        $scope.cancel = function () {
            $modalInstance.dismiss('cancel');
        };
    };

I have written a blog article on this subject and includes how to write tests for directives that use $inject:

transitioning-to-angular-2-0-part-2

Jesse Sanders
  • 511
  • 6
  • 13