web-dev-qa-db-fra.com

Existe-t-il un moyen de fermer automatiquement Angular UI Bootstrap modal lorsque l'itinéraire change?

J'ai des liens dans les modèles à l'intérieur des modaux. Lorsque je clique dessus, la page actuelle change, mais la superposition et le mode restent. Je pourrais ajouter ng-click="dimiss()" à chaque lien dans tous les modèles dans les modaux, mais y a-t-il une meilleure façon? Par exemple. pour le fermer automatiquement en cas de changement d'itinéraire réussi ou en ajouter un seul ng-click par modèle pour gérer tous les liens?

52
szimek

Si vous souhaitez que tous les modaux ouverts soient fermés chaque fois qu'un itinéraire est modifié avec succès, vous pouvez le faire en un seul endroit central en écoutant le $routeChangeSuccess événement, par exemple dans un bloc d'exécution de votre application:

var myApp = angular.module('app', []).run(function($rootScope, $uibModalStack) {
  $uibModalStack.dismissAll();
}); 

Ici, vous pouvez voir que le $uibModalStack le service est injecté sur lequel vous pouvez appeler la méthode dismissAll - cet appel fermera tous les modaux actuellement ouverts.

Donc, oui, vous pouvez gérer les modaux en fermeture centrale, en un seul endroit, avec une seule ligne de code :-)

100

Une meilleure façon est de voir que chaque fois qu'un Popup (Modal) est ouvert, lorsque vous cliquez sur le bouton Précédent du navigateur (ou Keyboard Back), nous arrêtons le changement d'URL et fermons simplement le Popup. Cela fonctionne pour une meilleure expérience utilisateur dans mon projet.

Le bouton Précédent du navigateur fonctionne normalement s'il n'y a pas de modal ouvert.

utilisation:

$uibModalStack.dismiss(openedModal.key);

ou

$uibModalStack.dismissAll;

Exemple de code:

.run(['$rootScope', '$uibModalStack',
    function ($rootScope,  $uibModalStack) {       
        // close the opened modal on location change.
        $rootScope.$on('$locationChangeStart', function ($event) {
            var openedModal = $uibModalStack.getTop();
            if (openedModal) {
                if (!!$event.preventDefault) {
                    $event.preventDefault();
                }
                if (!!$event.stopPropagation) {
                    $event.stopPropagation();
                }
                $uibModalStack.dismiss(openedModal.key);
            }
        });
    }]);
14
GamaSharma

Je n'utilise pas vraiment Angular UI Bootstrap, mais en regardant le docs , il semble qu'il y ait une méthode close() sur le $modalInstance objet.

Donc, en prenant l'exemple de la docs , cela devrait fonctionner:

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

    // this will listen for route changes and call the callback
    $scope.$on('$routeChangeStart', function(){
        $modalInstance.close();
    });
};

J'espère que ça t'as aidé.

3
tennisgent

J'ai résolu ce problème en faisant quelque chose comme ceci:

$rootScope.$on('$stateChangeSuccess',
function(event, toState, toParams, fromState, fromParams){
$modalStack.dismissAll();
});
2
kiran.gilvaz

Je garde cette logique dans le contrôleur modal. Vous pouvez écouter $locationChangeStart événement et fermer modal là-bas. Il est également bon de supprimer l'écouteur après, surtout si vous avez enregistré un écouteur sur $rootScope:

angular.module('MainApp').controller('ModalCtrl',['$scope','$uibModalInstance',
function ($scope, $uibModalInstance) {

  var dismissModalListener = $scope.$on('$locationChangeStart', function () {
    $uibModalInstance.close();
  });

  $scope.$on('$destroy', function() {
    dismissModalListener();
  });

}]);
1
Khrystyna Skvarok

L'ajout d'une réponse alternative.

Selon votre projet, l'utilisation de $uibModalStack.dismissAll() peut déclencher un message d'erreur.

Comme expliqué par JB Nizet dans la réponse this , elle est causée par dismissAll() rejetant une promesse, conduisant à un rappel 'échec' par opposition à un ' callback de succès déclenché par close().

Le rejet de cette promesse pourrait déclencher une procédure de gestion des erreurs potentiellement indésirable.

Étant donné qu'il n'y a pas de closeAll() dans $uibModalStack, J'ai utilisé ceci:

    var modal = $uibModalStack.getTop();
    while (modal && this.close(modal.key)) {
      modal = this.getTop();
    }

C'est le même comportement que $uibModalStack.dismissAll() mais utilise.close() au lieu de .dismiss().

Je n'ai trouvé aucune documentation décrivant les méthodes publiques pour $uibModalStack, Donc, au cas où quelqu'un serait intéressé à utiliser/regarder d'autres méthodes disponibles sur $uibModalStack.

Il sera probablement situé dans \node-modules\angular-ui-boostrap\dist\ui-boostrap-tpls.js Et dismissAll() est @ ligne 4349

Ça m'a pris du temps pour le trouver.

0
mrOak

vérifiez les conditions de route respectives dans l'événement $stateChangeSuccess puis fermez les modaux ouverts bootstrap globalement en utilisant la classe comme ceci:

$rootScope.$on('$stateChangeSuccess',
function(event, toState, toParams, fromState, fromParams){
//hide any open bootstrap modals
  angular.element('.inmodal').hide();
});

Si vous souhaitez masquer d'autres modaux tels que angular ($mdDialog) Et la boîte de dialogue d'alerte douce, utilisez angular.element('.modal-dialog').hide(); & angular.element('.sweet-alert').hide();

0
Sri7