Angular UI Bootstrap‘s $modal service has a $scope argument that lets you assign it whatever $scope you want, so if you wanted your modal’s controller to use the same $scope as your parent controller you could do that.

But what if you don’t want to use $scope? What if you’re using controllerAs and you want to keep your code all scope-less, neat, and tidy?

Luckily there’s an alternative. You can send your data to the modal as resolves. Resolves first appeared with ngRoute, as a way to make sure information was available to a route’s controller before the view was initiated. It prevents elements shifting around in your view as data would otherwise be loaded after the view shows up. It also keeps common data-loading tasks out of your controller.

Let’s look at an example. You’ve got a list of people in a table. Each has a name, and a delete button. When the user clicks the delete button a modal will come up confirming the delete.

We’ll pass the list of people and the person to delete into the modal’s controller using the resolve argument. Each property in the resolve object can be a string or function. If it’s a string, Angular will look for a service with that name and inject it into the modal controller. If it’s a function you can either return the value directly or return a promise if you’re fetching the data asynchronously.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 Main . $ inject = [ '$modal' ] ; function Main ( $ modal ) { var vm = this ; vm . deleteModal = deleteModal ; vm . people = [ 'Fred' , 'Jim' , 'Bob' ] ; function deleteModal ( person ) { $ modal . open ( { templateUrl : 'modal.html' , controller : [ '$modalInstance' , 'people' , 'person' , DeleteModalCtrl ] , controllerAs : 'vm' , resolve : { people : function ( ) { return vm . people } , person : function ( ) { return person ; } } } ) ; }

And just for clarity here’s our view, with the people ng-repeat ed in a table:

1 2 3 4 5 6 7 8 < table class = "table" > < tr ng - repeat = "p in vm.people" > < td > { { p } } < / td > < td > < button type = "button" class = "btn btn-sm btn-primary" ng - click = "vm.deleteModal(p)" > Delete < / button > < / td > < / tr > < / table >

Alright, there’s our people and our person; person is passed in to the deleteModal function when the user clicks a delete button, deleteModal in turn passes people and person to DeleteModalCtrl as injectables.

Our modal controller can look like this:

1 2 3 4 5 6 7 8 9 10 11 function DeleteModalCtrl ( $ modalInstance , people , person ) { var vm = this ; vm . person = person ; vm . deletePerson = deletePerson ; function deletePerson ( ) { people . splice ( people . indexOf ( person ) , 1 ) ; $ modalInstance . close ( ) ; } }

The injectables get passed in as arguments and we don’t need to use $scope at all, hooray! Finally, here is an example plunker showing how this all works together: