20

plunk: http://plnkr.co/edit/85Wl5W If I use the $modalInstance on the same controller(modalController.js), without being in a modal, angular gets frozen.

I just want to simplify my life using angularjs with the angular-ui bootstrap modal service. I want to use the same controller on a separate file, but on a modal as well. That is, I want them to do the same task. Is there any proper way to do it?

E.g. modal.html, modalController.js. I want to show these on a modal window, but on my application as well without a modal. The issue is that if I use the same controller I can't inject the $modalInstance, as it's undefined if there's no modal.

Thanks in advance,

Alex

Alex Arvanitidis
  • 4,403
  • 6
  • 26
  • 36

3 Answers3

30

It was possible in older version of UI-Bootstrap 0.10.0 .Even latest version,it works for me

index.html

<!-- if you are using Bower -->    
<script src="bower_components/angular-bootstrap/ui-bootstrap.min.js">
</script>
<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js">
</script>

<!-- modal -->
<!-- look at 'type' and 'id' values -->
<script type="text/ng-template" id="myTestModal.tmpl.html">
    <div class="modal-header">
        <h3>Modal Header</h3>
    </div>   

    <div class="modal-body">
        <p>Modal Body</p>
    </div>

    <div class="modal-footer">
        <button type="button" class="btn btn-default" ng-click="close()" data-dismiss="modal">Close
        </button>
        <button type="button" class="btn btn-primary" ng-click="doSomething()">Do Something
        </button>
    </div> 
</script>

modalDemoController.js

$scope.openModal=function(){
    $scope.modalInstance=$modal.open({
        templateUrl: 'myTestModal.tmpl.html',
        scope:$scope
    });
}

$scope.close=function(){
    $scope.modalInstance.dismiss();//$scope.modalInstance.close() also works I think
};

$scope.doSomething=function(){
    //any actions to take place
    console.log("Do Something");
}
Sajin M Aboobakkar
  • 4,051
  • 4
  • 30
  • 39
  • This seems like a good solution as well! If _if($scope.modalInstance)_ works then it could be used to avoid creating 2 controllers. – Alex Arvanitidis Oct 29 '14 at 11:20
  • 2
    A side note: if `modalInstance` is not something to reference from a view (HTML) then I would not store that into `$scope`. I think it would be better to keep that as a controller (private) *field*. – superjos Oct 29 '14 at 14:28
  • 3
    Not sure if you can do this with version before 0.12.0, but you can use $close(result) and $dismiss(reason) directly in the modal markup for the ng-click targets, instead of passing the targets on the modalInstance. Then you can act on the promise returned from "modalInstance.result", as you would with a typical modal. – Spencer Kormos Jan 03 '15 at 03:51
  • how to pass data from the main controller to the modal with this approach – SitecoreNoob Aug 10 '15 at 05:10
  • inheriting the parent scope in directive `scope:$scope` – Sajin M Aboobakkar Aug 10 '15 at 10:06
  • 2
    @SpencerKormos using `$close()` was just the solution I needed, thanks. – James Gentes Oct 22 '15 at 21:28
  • Works fine with latest bootstrap. – Mohammed Aamir K Aug 07 '16 at 12:54
6

I haven't found a clean solution yet, the best workaround I found, to avoid writing the same code twice was to extend the modal controller like this:

$.extend(this, $controller('NormalCtrl', {$scope: $scope}));

full controller:

.controller('ModalCtrl', ['$scope', '$controller', '$modalInstance', 
function ($scope, $controller, $modalInstance) {
    //with this line here:
    // Initialize the super class and extend it.
    $.extend(this, $controller('NormalCtrl', {$scope: $scope}));

    // Opens a search result
    $scope.openResult = function() {
        $modalInstance.close($scope.selectedRow);
    };

    // Called when the cancel button is pressed
    $scope.back = function() {
        $modalInstance.dismiss('cancel');
    };

}]);

That way, I can re-use the same code, without having to rewrite it all over again and I can override the functions that I want to do smth different to the original controller.

Hope I helped some people out there,

Alex

Alex Arvanitidis
  • 4,403
  • 6
  • 26
  • 36
4

Just write a function instead of creating new file:

 $scope.yourModal= function (data) {
   var modalInstance = $modal.open({
     template: '<div>Do you really want to hurt me? <div><button class="btn" ng-click="hurt(data)">Yes</button></div></div>',
     controller: function($scope, scope){
        $scope = scope;
     },
     resolve: {
         scope: function () {
            return $scope;
         }
     },
     size: 'sm'
   });  
 }

 $scope.hurt = function(data){
     console.log(data);
 }
Jordan.J.D
  • 7,999
  • 11
  • 48
  • 78
Anton Temchenko
  • 1,440
  • 1
  • 13
  • 28