2014-08-27 98 views
21

這是我的問題,我有兩個視圖(View1和View2)和一個控制器爲每個視圖(Ctrl1和Ctrl2)。在View1中,我試圖在用戶意外離開頁面之前警告用戶,而不保存更改。我使用window.onbeforeunload,它工作得很好,但我的問題是,即使我只有一個控制器onbeforeunload,事件似乎也在第二個控制器中觸發!但我甚至沒有那個事件在那裏。當用戶離開頁面並且存在未保存的更改時,如果用戶關閉警報並離開頁面,他會被onbeforeunload警告,如果用戶試圖離開該另一個視圖,他將被帶回到第二個視圖,我們也會收到關於未保存更改的警告!甚至沒有這種情況!這是爲什麼發生?AngularJS window.onbeforeunload在一個控制器上被另一個控制器觸發

我還使用$ locationChangeStart,這工作得很好,但只有當用戶改變了路線,而不是當他們刷新瀏覽器,點擊「後退」,或試圖關閉它,這就是爲什麼我被迫使用onbeforeunload(如果你更好的方法,請讓我知道)。任何幫助或更好的方法將不勝感激!

//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 ... 
} 

我試圖檢查與$ location.path電流通路()的時候,他是我想被觸發onb​​eforeunload的觀點僅向用戶發出警告,但這似乎有點「哈克」的解決方案將是根本不在另一個控制器上執行onbeforeload。

我在第一個中添加了$ location.path()!='/ view1'這似乎有效,但它對我來說似乎不太合適,除了我不僅有兩個視圖,幾個觀點,這會變得棘手有多個控制器參與:

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

回答

21

註銷onbeforeunload事件時將它定義控制器超出範圍:

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

正是我需要的!謝謝! – Poncho 2014-08-27 18:41:45

18

我只是嘗試了上述解決方案,以及沒有爲我工作。即使在控制檯中手動鍵入delete window.onbeforeunload也不會刪除該功能。我需要將該屬性設置爲undefined。

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

可能是因爲如果它們存在於原型鏈中,則無法刪除屬性。設置'onbeforeunload = undefined'爲我工作,而刪除沒有。 – spig 2015-03-03 17:19:09

+0

我遇到的確切問題,上面的答案解決了我的問題!謝謝!! – OmPrakash 2017-07-27 14:12:42

6

對於那些你使用angular-ui-router你會使用的是$stateChangeStart而不是$locationChangeStart,例如

$scope.$on('$stateChangeStart', function (event){ 
    if (forbit){ 
    event.preventDefault() 
    } 
    else{ 
    return 
    { 
}) 
相關問題