是否可以监听路由更改并且onwindowunload都可以确认页面休假而不保存更改?
用例:
如果用户点击“取消”,请停止更改页面/路线。
我见过几个不同的例子,但都没有做得很好。
答案 0 :(得分:22)
演示:http://plnkr.co/edit/Aq8uYg
在演示中,如果您更改输入值,则会在尝试返回时注意到。
收听$locationChangeStart
,如果未确认更改,请使用event.preventDefault()
取消位置更改。
此方法优于$route.reload()
:当前控制器和模型不会重新实例化。因此,所有变量都与用户单击“返回”按钮保持一致。
答案 1 :(得分:12)
您会发现$locationChangeStart
是您可以侦听以检测路线更改的事件。
尝试类似
的内容$rootScope.$on('$locationChangeStart', function (event, next, current) {
/* do some verification */
});
$route.reload()
将阻止路线更改。
用户点击或更改网址等之间的区别不会产生影响。由于浏览器在您更改网址#
之后不会重新加载任何资源,因此它仍然包含在您的角度逻辑中。这意味着所有这些方法都应该触发$locationChangeStart
事件。
$route
服务绝对会对您有用。 .reload()
方法会阻止路线更改完成,但如果您查看此问题,可以使用$route
服务做更多事情 - 请参阅documentation。
答案 2 :(得分:4)
我只会在你的$ rootScope上维护一个属性,如hasUnsavedEdits
。
function confirmLeavePage(e) {
var confirmed;
if ($rootScope.hasUnsavedEdits) {
confirmed = $window.confirm("You have unsaved edits. Do you wish to leave?");
if (e && !confirmed) {
e.preventDefault();
}
}
}
$window.addEventListener('beforeunload', confirmLeavePage);
$rootScope.$on("$locationChangeStart", confirmLeavePage);
您可能需要稍微调整一下代码来处理这两个条件。有关详细信息,请参阅demo。
答案 3 :(得分:4)
这也是很好的链接 http://weblogs.asp.net/dwahlin/cancelling-route-navigation-in-angularjs-controllers
function init() {
//initialize data here..
//Make sure they're warned if they made a change but didn't save it
//Call to $on returns a "deregistration" function that can be called to
//remove the listener (see routeChange() for an example of using it)
onRouteChangeOff = $rootScope.$on('$locationChangeStart', routeChange);
}
function routeChange(event, newUrl) {
//Navigate to newUrl if the form isn't dirty
if (!$scope.editForm.$dirty) return;
var modalOptions = {
closeButtonText: 'Cancel',
actionButtonText: 'Ignore Changes',
headerText: 'Unsaved Changes',
bodyText: 'You have unsaved changes. Leave the page?'
};
modalService.showModal({}, modalOptions).then(function (result) {
if (result === 'ok') {
onRouteChangeOff(); //Stop listening for location changes
$location.path(newUrl); //Go to page they're interested in
}
});
//prevent navigation by default since we'll handle it
//once the user selects a dialog option
event.preventDefault();
return;
}
答案 4 :(得分:0)
我创建了以下服务,其中包含其他答案中提供的信息(CoffeeScript,请参阅Plunker):
angular.module('myModule').service 'ChangeLossPreventer', ($rootScope, $q, $state) ->
confirmationMessage = null
service =
prevent: (message = 'Changed data will be lost. Continue?') ->
confirmationMessage = message
prompt: ->
confirmation = if confirmationMessage then confirm(confirmationMessage) else yes
if not confirmation
$q.reject()
else
$q.when(confirmation).then ->
service.cancel()
cancel: ->
confirmationMessage = null
$rootScope.$on '$stateChangeStart', (event, newState, newStateParams) ->
if confirmationMessage
event.preventDefault()
service.prompt().then ->
$state.go(newState, newStateParams)
window.onbeforeunload = ->
confirmationMessage
service
它基于angular-ui-router($state
服务的使用)。当您的网站进入可能丢失数据的状态时,您需要致电
ChangeLossPreventer.prevent("Optional warning message.");
当它存在此状态(即用户保存数据)时,您需要调用:
ChangeLossPreventer.cancel()
默认情况下,警告将在状态更改或关闭页面时显示(即刷新或转到其他网站)。您可能还需要验证执行其他操作是否安全(例如,如果有未保存的更改,请不要使用XHR注销):
$scope.logout = function() {
// confirmation will pop up only if there are unsaved changes
ChangeLossPreventer.prompt().then(function(){
// logout after confirmation
});
};
我创建了一个模拟它的Plunker。
答案 5 :(得分:0)
对于Angular ES6用户
export default class myRouteController {
constructor($scope, $window) {
this.$scope = $scope;
this.$window = $window;
this.$scope.$on('$stateChangeStart', (evt) => {
if(this.form.$dirty && !$window.confirm('Are you sure you want to leave this page?')) {
evt.preventDefault();
}
});
}
}