web-dev-qa-db-fra.com

Fermeture de Twitter Bootstrap Modal à partir du contrôleur angulaire

J'ai une fenêtre modale que j'utilise pour présenter un formulaire aux utilisateurs. Ils entrent l'information puis appuient sur un bouton qui a un clic droit. Le serveur traite la demande et renvoie une réponse. Lorsque la réponse est réussie, je souhaite fermer la fenêtre modale à partir du contrôleur. Comment cela peut il etre accompli?

Le modal est un partiel inclus dans une autre page

Page d'accueil:

<!-- main content -->
<p>Foo</p>
<!-- angular directive -->
<foo-directive></foo-directive>

Contenu de cette directive:

<div ng-controller="FooCtrl">
    <ul class="thumbnails">
        <li class="span3 tile tile-white" ng-repeat="foo in model.foo">
            <div>
                {{foo.bar}}
            </div>
            <div>
                ({{foo.bam}})
            </div>
            <div>
                <a data-toggle="modal" href="#myModal"><img src="{{foo.imgPath}}"></a>
            </div>
        </li>
    </ul>
    <!-- foo modal partial included by ejs -->
    <% include foo_modal.ejs %>
</div>

Balisage modal:

<div id="fooModal" class="modal hide fade in" style="display: none; ">
    <div class="modal-header">
        <a class="close" data-dismiss="modal">×</a>
        <h3>New Device</h3>
    </div>
    <div class="modal-body">
        <h4>Foo Modal</h4>
        <div ng-controller="FooCtrl">
            <form name="fooFrm">
                <input id="email" type="email" class="input-medium" ng-model="fooEmail"
                       placeholder="Email">
                <button class="btn btn-primary btn-small"
                        ng-click="doFoo({email:fooEmail})">Email Link</button>
            </form>
        </div>
    </div>
    <div class="modal-footer">
        <a href="#" class="btn" data-dismiss="modal">Close</a>
    </div>
</div>

Code du contrôleur:

functionFooCtrl($scope, FooService) {


    $scope.doFoo= function (email) {
       FooService.save({email:email.fooEmail}) {
            alert('Request successful');
            //TODO close Twitter bootstrap modal named fooModal here
        },
            function (err) {
                alert('Your request bonked, sorry');
                //TODO close Twitter bootstrap modal named fooModal here
            });
        }
    };

Quelle est la bonne façon de fermer le modal à partir du contrôleur dans les fonctions de succès et d'erreur?

Merci d'avance,

40
binarygiant

Avez-vous regardé angular-ui bootstrap ? Il existe une directive Dialog (ui.bootstrap.dialog) qui fonctionne assez bien. Vous pouvez fermer la boîte de dialogue pendant le rappel de manière angulaire (selon l'exemple):

$scope.close = function(result){
  dialog.close(result);
};

Mettre à jour:

La directive a depuis été renommée Modal .

21
Foo L

Nous pouvons réaliser la même chose sans utiliser angular-ui. Cela peut être fait en utilisant des directives angulaires.

Ajoutez d’abord la directive au modal.

<div class="modal fade" my-modal ....>...</div>

Créer une nouvelle directive angulaire:

app.directive('myModal', function() {
   return {
     restrict: 'A',
     link: function(scope, element, attr) {
       scope.dismiss = function() {
           element.modal('hide');
       };
     }
   } 
});

Appelez maintenant la méthode licencier () de votre contrôleur.

app.controller('MyCtrl', function($scope, $http) {
    // You can call dismiss() here
    $scope.dismiss();
});

Je suis encore dans mes débuts avec js angulaire. Je sais que nous ne devrions pas manipuler le DOM à l'intérieur des contrôleurs. J'ai donc la manipulation du DOM dans la directive. Je ne suis pas sûr que ce soit tout aussi mauvais. Si j'ai une meilleure alternative, je la posterai ici.

La chose importante à noter est que nous ne pouvons pas simplement utiliser ng-hide ou ng-show dans la vue pour masquer ou afficher le modal. Cela cache simplement le fond modal et non le fond modal. Nous devons appeler la méthode d'instance modal () pour supprimer complètement le modal. 

49
isubuz

Vous pouvez le faire comme ça:

angular.element('#modal').modal('hide');
33
Jonathan Flores

Voici une directive angulaire réutilisable qui cachera et montrera un modal Bootstrap.

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

            }

        }
    };

});

Exemple d'utilisation n ° 1 - Ceci suppose que vous souhaitiez afficher le modal - vous pouvez ajouter ng-if comme condition.

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

Exemple d'utilisation n ° 2: utilise une expression angulaire dans l'attribut modal-visible.

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

Autre exemple - pour démontrer l'interaction entre contrôleurs, vous pouvez ajouter quelque chose comme ceci à votre contrôleur. Le modal s'affiche après 2 secondes, puis masqué après 5 secondes.

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

Je suis en retard pour contribuer à cette question - créé cette directive pour une autre question ici. Directive angulaire simple pour Bootstrap Modal

J'espère que cela t'aides.

5
Ender2050

Vous pouvez ajouter data-rejet = "modal" à vos attributs de bouton qui appellent la fonction angularjs.

Tel que;

<button type="button" class="btn btn-default" data-dismiss="modal">Send Form</button>
1
maskapsiz

J'ai remixé la réponse de @ isubuz et cette réponse de @Umur Kontacı sur les directives d'attribut dans une version dans laquelle votre contrôleur n'appelle pas une opération de type DOM telle que "ignorer" être plus de style MVVM, définissant une propriété booléenne isInEditMode. La vue lie à son tour ce bit d’information à la directive attributaire qui ouvre/ferme le modal bootstrap.

var app = angular.module('myApp', []);

app.directive('myModal', function() {
   return {
     restrict: 'A',
     scope: { myModalIsOpen: '=' },
     link: function(scope, element, attr) {
       scope.$watch(
         function() { return scope.myModalIsOpen; },
         function() { element.modal(scope.myModalIsOpen ? 'show' : 'hide'); }
       );
     }
   } 
});

app.controller('MyCtrl', function($scope) {
  $scope.isInEditMode = false;
  $scope.toggleEditMode = function() { 
    $scope.isInEditMode = !$scope.isInEditMode;
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Twitter-bootstrap/3.3.6/js/bootstrap.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/Twitter-bootstrap/3.3.6/css/bootstrap.css" rel="stylesheet"/>

<div ng-app="myApp" ng-controller="MyCtrl as vm">

<div class="modal fade" my-modal my-modal-is-open="isInEditMode">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-body">
        Modal body! IsInEditMode == {{isInEditMode}}
      </div>
      <div class="modal-footer">
        <button class="btn" ng-click="toggleEditMode()">Close</button>
      </div>
    </div>
  </div>
</div>

<p><button class="btn" ng-click="toggleEditMode()">Toggle Edit Mode</button></p> 
<pre>isInEditMode == {{isInEditMode}}</pre>
  
</div>

0
Jeroen