2014-08-27 13 views
21

Ecco il mio problema, ho due visualizzazioni (View1 e View2) e un controller per ogni vista (Ctrl1 e Ctrl2). In View1 sto cercando di avvisare l'utente prima che lasci la pagina accidentalmente senza salvare le modifiche.AngularJS window.onbeforeunload in un controller viene attivato su un altro controller

Sto usando window.onbeforeunload, che funziona bene, ma il mio problema è che anche se ho onbeforeunload solo su un controller, l'evento sembra essere attivato anche nel secondo controller! Ma non ho nemmeno avuto quell'evento lì dentro. Quando l'utente lascia una pagina e ci sono modifiche non salvate, viene avvisato dal onbeforeunload, se l'utente chiude l'avviso e lascia la pagina, viene riportato alla seconda vista, se l'utente prova a lasciare questa altra vista, verremmo anche avvertiti in merito a modifiche non salvate! Quando non è nemmeno il caso! Perché sta succedendo?

Sto anche usando $ locationChangeStart, che funziona bene, ma solo quando l'utente cambia rotta, non quando aggiorna il browser, premi 'indietro', o prova a chiuderlo, ecco perché sono forzato per utilizzare onbeforeunload (Se avete un approccio migliore, per favore fatemelo sapere). Qualsiasi aiuto o un approccio migliore sarebbe molto apprezzato!

//In this controller I check for window.onbeforeunload 
app.controller("Ctrl1", function ($scope, ...)){ 
    window.onbeforeunload = function (event) {   

    //Check if there was any change, if no changes, then simply let the user leave 
    if(!$scope.form.$dirty){ 
     return; 
    } 

    var message = 'If you leave this page you are going to lose all unsaved changes, are you sure you want to leave?'; 
    if (typeof event == 'undefined') { 
     event = window.event; 
    } 
    if (event) { 
     event.returnValue = message; 
    } 
    return message; 
    } 

    //This works only when user changes routes, not when user refreshes the browsers, goes to previous page or try to close the browser 
    $scope.$on('$locationChangeStart', function(event) {  
    if (!$scope.form.$dirty) return; 
    var answer = confirm('If you leave this page you are going to lose all unsaved changes, are you sure you want to leave?') 
    if (!answer) { 
     event.preventDefault(); 
    } 
    }); 
} 

//This other controller has no window.onbeforeunload, yet the event is triggered here too! 
app.controller("Ctrl2", function ($scope, ...)){ 
    //Other cool stuff ... 
} 

ho provato a controllare il percorso corrente con $ location.path() per avvertire solo l'utente quando è nella visualizzazione voglio l'onbeforeunload per essere attivato, ma questo sembra un po 'hacky' la soluzione sarebbe non eseguire affatto onbeforeunload sull'altro controller.

Ho aggiunto $ location.path()! = '/ View1' nel primo che sembra funzionare, ma non mi sembra giusto, inoltre non ho solo due viste, ho diversi punti di vista e questo sarebbe ottenere difficile con più controllori coinvolti:

app.controller("Ctrl1", function ($scope, ...)){ 
    window.onbeforeunload = function (event) {   

    //Check if there was any change, if no changes, then simply let the user leave 
    if($location.path() != '/view1' || !$scope.form.$dirty){ 
     return; 
    } 

    var message = 'If you leave this page you are going to lose all unsaved changes, are you sure you want to leave?'; 
    if (typeof event == 'undefined') { 
     event = window.event; 
    } 
    if (event) { 
     event.returnValue = message; 
    } 
    return message; 
    } 

    //This works only when user changes routes, not when user refreshes the browsers, goes to previous page or try to close the browser 
    $scope.$on('$locationChangeStart', function(event) {  
    if (!$scope.form.$dirty) return; 
    var answer = confirm('If you leave this page you are going to lose all unsaved changes, are you sure you want to leave?') 
    if (!answer) { 
     event.preventDefault(); 
    } 
    }); 
} 

risposta

21

annullare la registrazione della manifestazione onbeforeunload quando il controllore che ha definito esce di portata:

$scope.$on('$destroy', function() { 
    delete window.onbeforeunload; 
}); 
+0

Esattamente quello che mi serviva! Grazie! – Poncho

18

ho appena tentato la soluzione di cui sopra, e che non stava funzionando per me. Anche digitando manualmente delete window.onbeforeunload nella console non si rimuove la funzione. Dovevo invece impostare la proprietà su undefined.

$scope.$on('$destroy', function(e){ 
    $window.onbeforeunload = undefined; 
}); 
+3

Probabilmente perché non è possibile eliminare le proprietà se esistono nella catena del prototipo. L'impostazione 'onbeforeunload = undefined' ha funzionato per me mentre l'eliminazione no. – spig

+0

Esatto problema che ho affrontato, la risposta di cui sopra risolto il mio problema !! Grazie!! – OmPrakash

6

Per quelli di voi che usano angular-ui-router si usa è $stateChangeStart invece di $locationChangeStart, per esempio

$scope.$on('$stateChangeStart', function (event){ 
    if (forbit){ 
    event.preventDefault() 
    } 
    else{ 
    return 
    { 
}) 
Problemi correlati