有在你試圖解決這整個問題的根源2個DOM事件:onhashchange和onbeforeunload。 onhashchange可以被檢查和阻止,但是,瀏覽器上的Back按鈕不會觸發onhashchange。更糟糕的是,如果頁面沒有重新加載,onbeforeunload將不會觸發,這意味着如果您點擊Back返回頁面上的前一個散列,它將不會觸發。正因爲如此,如果您按返回去以前的路線它仍然會離開您的表單。
目前還有一個oustanding issue on Angular's todo list關於他們將如何允許取消路線。我認爲後面的按鈕到哈希問題是什麼在這一點上支持他們。
所以最後你可能想重新設計你的解決方案,如果你想在表單被編輯後阻止所有的導航離開你的表單,那麼做一些更激烈的事情。就像存儲表單在$ rootScope中編輯的所有數據一樣,還有一個標誌以顯示它很髒但不完整,然後向routeChangeStart添加一個事件處理程序,該處理程序檢查這些值並將其發送回表單。
下面是如何將工作(和plunker if you're interested):
app.config(function($routeProvider) {
//set up the routes. (Important because we're going to navigate
// BACK to them.)
$routeProvider.when('/Form', {
controller: 'FormCtrl',
templateUrl: 'form.html'
}).otherwise({
controller: 'HomeCtrl',
template: '<h3>Home</h3>'
});
});
app.run(function($rootScope, $location){
//set up your rootScope formData object.
$rootScope.formData = {};
//add a routing event to check the route
// and whether or not the data has been editted and then
// send it back to the proper form.
$rootScope.$on('$routeChangeStart', function() {
if($location.path() != '/Form' && $rootScope.formData.dirty &&
!$rootScope.formData.complete && !confirm('Do you want to leave this form?')) {
$location.path('/Form');
}
});
//handle outright navigating away from the page.
$(window).on('beforeunload', function() {
if($rootScope.formData.dirty &&
!$rootScope.formData.complete) {
return 'Are you sure you want to navigate away from this form?';
}
});
});
app.controller('FormCtrl', function($scope) {
$scope.$watch(function(){
return $scope.myForm.$dirty;
}, function(dirty) {
$scope.formData.dirty = $scope.formData.dirty | dirty;
})
});
其他的想法
起初我制定了一項指令來解決這個問題,但我意識到,它不會因爲我上面提到的問題而工作。無論如何,爲後人的緣故,那就是:
app.directive('form', function ($window){
return {
restrict: 'E',
link: function(scope, elem, attrs) {
//check for a prevent-if-dirty attribute on your form tag
if(attrs.preventIfDirty !== undefined) {
// first off, stop routing hash changes from
// changing the page.
scope.$on('$locationChangeStart', function(event) {
if(scope.testForm.$dirty) {
event.preventDefault();
}
});
// a little setup for our next piece
var formName = attrs.name;
function showWarning() {
return 'You have changed the form';
}
// Now stop browser navigation from moving away
// from your dirty form.
scope.$watch(function(){
return scope[formName].$dirty;
}, function(dirty) {
if(dirty) {
$(window).on('beforeunload', showWarning);
} else {
$(window).off('beforeunload', showWarning);
}
});
}
}
};
});
Here's a plunker demonstrating it.
但仍然dat不會顯示提示要求確認,而不會允許用戶回去。 – iJade 2013-02-16 06:44:40
不應該難以添加...堅持。 – 2013-02-17 06:01:42
你走了。它現在會顯示確認。 – 2013-02-17 06:04:04