6

Anyone have a simple directive to automatically show a Bootstrap modal? In Bootstrap 3 they took away the ability to automatically show the modal so I can't use a angular ng-if show block. Any help would be great.

Lereveme
  • 1,614
  • 2
  • 15
  • 18

2 Answers2

18

Updated for angular 1.2 & Bootstrap 3.1.1: http://embed.plnkr.co/WJBp7A6M3RB1MLERDXSS/

I extended Ender2050's answer so the directive does not have an isolated scope. This means the modal contents can contain references to scope objects. Also reuse the directive attribute so only one attribute is needed.

app.directive("modalShow", function ($parse) {
    return {
        restrict: "A",
        link: function (scope, element, attrs) {

            //Hide or show the modal
            scope.showModal = function (visible, elem) {
                if (!elem)
                    elem = element;

                if (visible)
                    $(elem).modal("show");                     
                else
                    $(elem).modal("hide");
            }

            //Watch for changes to the modal-visible attribute
            scope.$watch(attrs.modalShow, function (newValue, oldValue) {
                scope.showModal(newValue, attrs.$$element);
            });

            //Update the visible value when the dialog is closed through UI actions (Ok, cancel, etc.)
            $(element).bind("hide.bs.modal", function () {
                $parse(attrs.modalShow).assign(scope, false);
                if (!scope.$$phase && !scope.$root.$$phase)
                    scope.$apply();
            });
        }

    };
});

Usage:

<div modal-show="showDialog" class="modal fade"> ...bootstrap modal... </div>
warrickh
  • 1,616
  • 1
  • 16
  • 14
  • This works like a charm, except that the modal disappeared behind my bootstrap navbar (due to the location of the modal in the DOM tree). I solved it by changing $(elem).modal("show") to $(elem).appendTo('body').modal("show"). – Erik Vullings Nov 19 '14 at 10:20
13

Here's an Angular directive that will hide and show a Bootstrap modal.

app.directive("modalShow", function () {
    return {
        restrict: "A",
        scope: {
            modalVisible: "="
        },
        link: function (scope, element, attrs) {

            //Hide or show the modal
            scope.showModal = function (visible) {
                if (visible)
                {
                    element.modal("show");
                }
                else
                {
                    element.modal("hide");
                }
            }

            //Check to see if the modal-visible attribute exists
            if (!attrs.modalVisible)
            {

                //The attribute isn't defined, show the modal by default
                scope.showModal(true);

            }
            else
            {

                //Watch for changes to the modal-visible attribute
                scope.$watch("modalVisible", function (newValue, oldValue) {
                    scope.showModal(newValue);
                });

                //Update the visible value when the dialog is closed through UI actions (Ok, cancel, etc.)
                element.bind("hide.bs.modal", function () {
                    scope.modalVisible = false;
                    if (!scope.$$phase && !scope.$root.$$phase)
                        scope.$apply();
                });

            }

        }
    };

});

Usage Example #1 - this assumes you want to show the modal - you could add ng-if as a condition

<div modal-show class="modal fade"> ...bootstrap modal... </div>

Usage Example #2 - this uses an Angular expression in the modal-visible attribute

<div modal-show modal-visible="showDialog" class="modal fade"> ...bootstrap modal... </div>

Another Example - to demo the controller interaction, you could add something like this to your controller and it will show the modal after 2 seconds and then hide it after 5 seconds.

$scope.showDialog = false;
$timeout(function () { $scope.showDialog = true; }, 2000)
$timeout(function () { $scope.showDialog = false; }, 5000)

I'm anxious to see what other solutions people come up with. Cheers!

Ender2050
  • 6,912
  • 12
  • 51
  • 55
  • 1
    Just plugged this in and it works great. Thanks for the fast response and for the link to Bootstrap 4 :) – Lereveme Oct 28 '13 at 20:48
  • "but don't want to include a big library right now" - so I've decided to include jQuery and Bootstrap's JavaScript... ehhh... – pkozlowski.opensource Oct 28 '13 at 21:48
  • 2
    This works but then it won't turn showDialog in controller's scope and also the attribute modal-visible accordingly to false again after I dismiss the the popover. Only it disappears from the DOM but that change is not reflected in the Model. What should I do ? – Amogh Talpallikar Nov 06 '13 at 10:50
  • Is this still valid? Any chance of a plnker? When I try and use it, I get TypeError: Object [object Object] has no method 'modal'. – bookthief Feb 27 '14 at 14:31
  • I don't understand why the $scope.$apply() is needed here (and I know it is)? – DevAntoine Aug 01 '14 at 13:27