当用户尝试单击浏览器后退按钮并且dere是表单上的脏数据时,它会显示确认信息。
这是角度js控制器代码
function MyCtrl2($rootScope, $location, $scope) {
$rootScope.$watch(function () {
return $location.path();
},
function (newValue, oldValue) {
if ($scope.myForm.$dirty) {
var a = confirm('do you');
if (!a) {
//how to prevent this redirect
}
}
},
true);
}
MyCtrl2.$inject = ['$rootScope', '$location', '$scope'];
但如何防止重定向
答案 0 :(得分:12)
现在可以在Angular取消路线。
$scope.$on('$locationChangeStart', function(event, newUrl, oldUrl) {
event.preventDefault();
});
答案 1 :(得分:2)
在您尝试解决的整个问题的根源上有两个DOM事件:onhashchange和onbeforeunload。可以检查并阻止onhashchange,但是,浏览器上的“后退”按钮不会触发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);
}
});
}
}
};
});