2015-04-08 13 views
10

Ich bin ein Modul aus den UI Bootstrap Erweiterungen (http://angular-ui.github.io/bootstrap). Das Modul dient tatsächlich als Ladedialog und wird automatisch geschlossen, wenn eine Reihe von Webservice-Daten an meinen Angular-Code zurückgegeben wird. Da die Daten auf dieser Seite automatisch geladen werden, erscheint der Dialog sofort.Angular UI Bootstrap-Modul Schließen nicht auf Back Button

Das alles funktioniert gut, wenn ich die betreffende Seite für den erste Mal treffen oder einfach aktualisieren. Das Problem tritt auf, wenn ich auf eine tiefere Seite gehe und dann versuche, über die Zurück-Schaltfläche des Browsers zur ursprünglichen Seite (mit dem Dialog) zurück zu navigieren. Der Dialog verschwindet trotz der Tatsache, dass alle Daten zurückgegeben werden und der Aufruf von follow() des Moduls erfolgt ist.

ich das verfolgt habe bis zu dem Versprechen, den Dialog zu öffnen erscheint, nachdem der Anruf abweisen zu geschehen, aber auch hier nur, wenn die Seite über die Zurück-Taste geladen wird. Der Ablehnungsaufruf schließt nie etwas, weil es noch nicht hinzugefügt wurde (ich habe dies im Debugger bestätigt).

Die Frage, die ich habe, ist, wie könnte ich damit umgehen? Gibt es einen soliden Weg, die Beendigung des Ladens der Seite über Angular abzufangen und zu überprüfen, ob der Dialog geschlossen ist? Gibt es einen besseren Weg über UI Bootstrap's API?

Ich weiß, das ist eher ungewöhnlich, aber alle Gedanken daran wäre toll.

Danke!

+0

Mögliche Duplikat [? gibt es eine Möglichkeit, automatisch Angular UI Bootstrap modal, wenn Routenänderungen schließen] (https://stackoverflow.com/questions/23762323/is-there-a -way-to-automatisch-close-eckig-ui-bootstrap-modal-wenn-route-chan) – Johann

Antwort

3

Ich habe in das gleiche Problem laufen. Hier ist, wie ich es behoben habe.

1) Erstellen Sie einen Dienst, um das Öffnen und Schließen eines Modals zu abstrahieren und zu verfolgen, welches geöffnet ist (erforderlich für Schritt 2). Rufen Sie statt $modal.open() direkt ModalService.open() an. Hier gehen Sie, können Sie das eine habe ich geschrieben:

(function() { 
    'use strict'; 

    var theModule = angular.module('services.modalService', ['ui.bootstrap']); 

    theModule.factory('ModalService', function ($modal) { 
     var service = {}; 
     var currentModal; 
     var clearModal = function() { 
      currentModal = undefined; 
     }; 

     service.getCurrentModal = function() { 
      return currentModal; 
     }; 

     service.open = function (options) { 
      currentModal = $modal.open(options); 
      currentModal.result['finally'](clearModal); 
      return currentModal; 
     }; 

     return service; 
    }); 
}()); 

2) In einem Controller, fügen Sie einen Ereignis-Listener $routeChangeStart, wird dieses Ereignis ausgelöst, wenn jemand die Zurück-Taste trifft.

3) Ihre Mods sollten jetzt geschlossen werden, wenn ein Benutzer zurückschlägt.

4) Genießen. Hier

+0

Würde dies funktionieren die Seite wird von oder für die Zielseite navigiert? Das Problem ist nicht, dass die Seite, von der ich gehe, aufgeräumt wird, sondern die unterschiedliche Abfolge von Ereignissen zum Laden auf der Zielseite. –

+0

Ich habe tatsächlich etwas ähnliches getan, aber ich habe mich in einen leeren Show-Handler am Ende der Seite (ein totaler Hack) eingehakt. Ich hoffe, es gibt einen besseren Weg, aber es funktioniert. –

+0

Re-Lesen Ihrer ursprünglichen Post, es klingt wie die Ursache dieses Problems ist, dass das modale Popup wird geöffnet 100% der Zeit (wenn diese Seite geladen wird), auch wenn es nicht benötigt wird, ist das korrekt? – HankScorpio

5

ist die einfache Lösung, wenn ui-Router für den Zustandswechsel mit

Closing modalen Popup auf den Zurück-Button klicken in AngularJS

App.run(['$rootScope', '$modalStack', function ($rootScope, $modalStack) { 
    $rootScope.$on('$stateChangeStart', function (event) { 
     var top = $modalStack.getTop(); 
     if (top) { 
      $modalStack.dismiss(top.key); 
     } 
    }) 
}]); 

hoffen, dass diese viel Zeit sparen wird Leute, die Köpfe brechen

0

VERBESSERUNG:

Ich fand die Antwort von HankScorpio die beste da draußen zu sein. Ich wollte diesen Ausschnitt für diejenigen, die Ui-Router und ihre Empfehlung für stateful modals verwenden.

1) Ich wollte das Ergebnis.finally (...) um zu einem Elternstatus zu springen;
2) Ich wollte das Schließen des modalen von $ stateProvider Config steuern, nicht durch einen Controller Rigging und einen Zuhörer zu $ ​​routeChangeStart Hinzufügen

Hier ein Beispiel für einen Zustand ist, das (öffnet und schließt) es ist modal:

 .state('product.detail', { 
      url: '/detail/{productId}', 
      onEnter: /*open-modal logic*/, 
      onExit: ['ModalService', function (ModalService) { ModalService.close()} ]     
     }) 

ich machte ModalService von $ Zustand bewusst so, dass das Ergebnis einer modalen des Schließens zu einer übergeordneten Ansicht springen könnte:

einen

. Fügen Sie ein isStateful Flagge modalService.open (...):

service.open = function (options, isStateful) { 
    currentModal = $uibModal.open(options); 
    currentModal.result.finally(function() { 
     clearModal(isStateful); 
    }); 
    return currentModal; 
}; 

so dass clearModal zum vorherigen Zustand zurück:

var clearModal = function (isStateful) { 
     currentModal = undefined; 
     if (isStateful) 
      $state.go('^'); 
    }; 

Schließlich fügen Sie die closeModal() Funktion oben genannt (nicht eine „Stateful“ schließen, einfach eine Entlassung):

service.close = function() { 
     if (currentModal) { 
      currentModal.dismiss().then(function() { 
       clearModal(); 
      }) 
     } 
    } 

Die Vorteile sind, dass back-Button-Funktionalität im Zustand Konfigurationsebene gesteuert wird, nicht durch einen Zuhörer.

6

@ HankScorpios Lösung ist gut, aber ich denke, dass es jetzt eine vereinfachte Option geben kann.

Es besteht keine Notwendigkeit mehr, den aktuellen modal zu speichern, wenn Sie sich registrieren entweder eine $locationChangeStart oder $routeChangeStart Zuhörer mit $uibModalStack injiziert und $uibModalStack.dismissAll() nennen. $locationChangeStart hat den Vorteil, sowohl für ngRoute als auch für uRoute zu arbeiten.

Wenn also nur für die eine Seite, dann in Ihrem Controller müßten Sie:

angular.module('app') 
    .controller('ctrl', ['$scope', '$uibModalStack', ctrl]); 

function ctrl($scope, $uibModalStack) { 
    $scope.$on('$locationChangeStart', handleLocationChange); 

    function handleLocationChange() { 
     $uibModalStack.dismissAll(); 
    } 
} 

Wenn Sie dies für alle Seiten tun wollen, dann diese in einer Fabrik definieren, die immer geladen ist oder nur ein app.run Codesegment:

+2

Nur eine Anmerkung, dass je nach der Version von ui-bootstrap $ modalStack anstelle von $ uibModalStack verwenden kann (aktuell ist $ uibModalStack) – TheMcMurder

+0

Wenn Sie möchten, dass die Schaltfläche Zurück den Dialog schließt, aber nicht zurück in den Verlauf, können Sie Überprüfen Sie, ob '$ uibModalStack.getTop()' irgendwas zurückgibt und nur in diesem Fall _und auch_ 'event.preventDefault()' ablehnt ('event' wird an' handleLocationChange() 'übergeben). – bigstones