是什么导致 'beforeunload' 事件在 Chrome 中被触发?
What causes the 'beforeunload' event to be triggered in Chrome?
我正在添加一个事件侦听器 'beforeunload' 来检查表单是否脏了,并向我的用户提供一条消息,即离开该页面可能会导致他们丢失未保存的数据。由于我在 Chrome,我知道我不能设置自定义消息,但基本上我必须添加事件侦听器才能显示默认消息。当我的表单变脏时,该消息确实出现了,但是除了重新加载页面之外,我不知道如何重置它。我的问题是:是什么导致 'beforeunload' 事件被触发?对我来说,它只会在我的表单变脏时触发,但由于我没有设置它,所以我不确定一旦触发事件如何将其关闭。
我已经尝试在用户确认他们想要离开页面时删除事件侦听器,但是当我单击返回页面并尝试重新加载时,事件仍然会触发,即使表单没有变脏甚至 pristine 也被设置为 true。
这是控制器中的相关代码。
var unloadEvent = function (e) {
e.returnValue = '';
};
window.addEventListener("beforeunload", unloadEvent);
// For when a user hits the back button
$transitions.onBefore({}, function ($transition)
{
console.log("on before", vm.ticketForm);
if (vm.ticketForm && vm.ticketForm.$dirty == true) {
var answer = confirm("Are you sure you want to leave this page? Changes you made may not be saved.")
if (!answer) {
// User would like to cancel the click and remain on the page
$window.history.forward();
$transition.abort();
return false;
}
else {
// Form is dirty but user would like to leave the page
// Set the form to pristine
window.removeEventListener("beforeunload", unloadEvent);
vm.ticketForm.$setPristine();
vm.ticketForm.$setUntouched();
}
}
});
$scope.$on('$destroy', function() {
window.removeEventListener("beforeunload", unloadEvent);
});
这是 html
的一部分
<form name="detailVM.ticketForm">
<table class="table table-condensed table-striped table-center">
<tbody>
<tr>
<th>Username</th>
<th>Worker Number</th>
<th></th>
<th>Start Time</th>
<th>End Time</th>
<th>Adjusted Start Time</th>
<th>Adjusted End Time</th>
<th></th>
</tr>
<tr ng-repeat="worker in detailVM.currentTicket.crew_assignment.workers" ng-if="worker.revised_start_timestamp !== null && worker.revised_end_timestamp !== null">
<td>{{::worker.worker_username}}</td>
<td>{{::worker.worker_number}}</td>
<td><a href="#">Edit Shift</a></td>
<td>{{ ::detailVM.formatTime(worker.current_start_timestamp, 'MM/DD/YYYY, h:mm:ss a') }}</td>
<td>{{ ::detailVM.formatTime(worker.current_end_timestamp, 'MM/DD/YYYY, h:mm:ss a') }}</td>
<td><input type="datetime-local" ng-model="worker.revised_start_timestamp" ng-change="detailVM.changeWorkerStartTime(worker, worker.start_timestamp)"></td>
<td><input type="datetime-local" ng-model="worker.revised_end_timestamp" ng-change="detailVM.changeWorkerEndTime(worker, worker.end_timestmap)"></td>
<td>
<button ng-click="detailVM.deleteWorker(worker)">
<span class="fa fa-trash"></span>
</button>
</td>
</tr>
<tr ng-if="detailVM.newWorkerFormShown">
<td>
<input type="string" ng-model="detailVM.newWorkerName"/>
</td>
<td>
<input type="string" ng-model="detailVM.newWorkerNumber"/>
</td>
<td>
<input type="datetime-local" ng-model="detailVM.newWorkerStartTimestamp"/>
</td>
<td>
<input type="datetime-local" ng-model="detailVM.newWorkerEndTimestamp"/>
</td>
<td>
<button ng-click="detailVM.addWorker()">
<span class="fa fa-plus addButton"></span>
</button>
</td>
</tr>
</tbody>
</table>
</form>
我不清楚是什么导致事件触发,因为它只是偶尔触发。据我所知,它只在表单被触摸后触发,然后即使事件侦听器被删除然后重新添加也会继续触发。
I am adding an event listener 'beforeunload' to check if a form is dirty or not and provide a message to my users that navigating away from the page might cause them to l
ose unsaved data.
一种方法是为 form
指令创建自定义指令:
app.directive("confirmDirtyUnload", function($window) {
return {
require: "ngForm",
link: postLink,
};
function postLink(scope, elem, attrs, ngForm) {
$window.addEventListener("beforeunload", checkDirty);
elem.on("$destroy", function (ev) {
$window.removeEventListener("beforeunload", checkDirty);
});
function checkDirty(event) {
if (ngForm.$dirty) {
// Cancel the event as stated by the standard.
event.preventDefault();
// Chrome requires returnValue to be set.
event.returnValue = '';
};
}
}
});
用法:
<form confirm-dirty-unload name="form1">
<input name="text1" ng.model="data.text1" />
</form>
我正在添加一个事件侦听器 'beforeunload' 来检查表单是否脏了,并向我的用户提供一条消息,即离开该页面可能会导致他们丢失未保存的数据。由于我在 Chrome,我知道我不能设置自定义消息,但基本上我必须添加事件侦听器才能显示默认消息。当我的表单变脏时,该消息确实出现了,但是除了重新加载页面之外,我不知道如何重置它。我的问题是:是什么导致 'beforeunload' 事件被触发?对我来说,它只会在我的表单变脏时触发,但由于我没有设置它,所以我不确定一旦触发事件如何将其关闭。
我已经尝试在用户确认他们想要离开页面时删除事件侦听器,但是当我单击返回页面并尝试重新加载时,事件仍然会触发,即使表单没有变脏甚至 pristine 也被设置为 true。
这是控制器中的相关代码。
var unloadEvent = function (e) {
e.returnValue = '';
};
window.addEventListener("beforeunload", unloadEvent);
// For when a user hits the back button
$transitions.onBefore({}, function ($transition)
{
console.log("on before", vm.ticketForm);
if (vm.ticketForm && vm.ticketForm.$dirty == true) {
var answer = confirm("Are you sure you want to leave this page? Changes you made may not be saved.")
if (!answer) {
// User would like to cancel the click and remain on the page
$window.history.forward();
$transition.abort();
return false;
}
else {
// Form is dirty but user would like to leave the page
// Set the form to pristine
window.removeEventListener("beforeunload", unloadEvent);
vm.ticketForm.$setPristine();
vm.ticketForm.$setUntouched();
}
}
});
$scope.$on('$destroy', function() {
window.removeEventListener("beforeunload", unloadEvent);
});
这是 html
的一部分 <form name="detailVM.ticketForm">
<table class="table table-condensed table-striped table-center">
<tbody>
<tr>
<th>Username</th>
<th>Worker Number</th>
<th></th>
<th>Start Time</th>
<th>End Time</th>
<th>Adjusted Start Time</th>
<th>Adjusted End Time</th>
<th></th>
</tr>
<tr ng-repeat="worker in detailVM.currentTicket.crew_assignment.workers" ng-if="worker.revised_start_timestamp !== null && worker.revised_end_timestamp !== null">
<td>{{::worker.worker_username}}</td>
<td>{{::worker.worker_number}}</td>
<td><a href="#">Edit Shift</a></td>
<td>{{ ::detailVM.formatTime(worker.current_start_timestamp, 'MM/DD/YYYY, h:mm:ss a') }}</td>
<td>{{ ::detailVM.formatTime(worker.current_end_timestamp, 'MM/DD/YYYY, h:mm:ss a') }}</td>
<td><input type="datetime-local" ng-model="worker.revised_start_timestamp" ng-change="detailVM.changeWorkerStartTime(worker, worker.start_timestamp)"></td>
<td><input type="datetime-local" ng-model="worker.revised_end_timestamp" ng-change="detailVM.changeWorkerEndTime(worker, worker.end_timestmap)"></td>
<td>
<button ng-click="detailVM.deleteWorker(worker)">
<span class="fa fa-trash"></span>
</button>
</td>
</tr>
<tr ng-if="detailVM.newWorkerFormShown">
<td>
<input type="string" ng-model="detailVM.newWorkerName"/>
</td>
<td>
<input type="string" ng-model="detailVM.newWorkerNumber"/>
</td>
<td>
<input type="datetime-local" ng-model="detailVM.newWorkerStartTimestamp"/>
</td>
<td>
<input type="datetime-local" ng-model="detailVM.newWorkerEndTimestamp"/>
</td>
<td>
<button ng-click="detailVM.addWorker()">
<span class="fa fa-plus addButton"></span>
</button>
</td>
</tr>
</tbody>
</table>
</form>
我不清楚是什么导致事件触发,因为它只是偶尔触发。据我所知,它只在表单被触摸后触发,然后即使事件侦听器被删除然后重新添加也会继续触发。
I am adding an event listener 'beforeunload' to check if a form is dirty or not and provide a message to my users that navigating away from the page might cause them to l ose unsaved data.
一种方法是为 form
指令创建自定义指令:
app.directive("confirmDirtyUnload", function($window) {
return {
require: "ngForm",
link: postLink,
};
function postLink(scope, elem, attrs, ngForm) {
$window.addEventListener("beforeunload", checkDirty);
elem.on("$destroy", function (ev) {
$window.removeEventListener("beforeunload", checkDirty);
});
function checkDirty(event) {
if (ngForm.$dirty) {
// Cancel the event as stated by the standard.
event.preventDefault();
// Chrome requires returnValue to be set.
event.returnValue = '';
};
}
}
});
用法:
<form confirm-dirty-unload name="form1">
<input name="text1" ng.model="data.text1" />
</form>