У нас есть следующая функция, которая показывает диалоговое окно подтверждения пользователю, когда есть несохраненные изменения, и пользователь пытался уйти.
$scope.$on('$stateChangeStart', (event, toState, toParams, __fromState, fromParams) => {
if (fromParams.userConfirmedRedirect) {
return;
}
const checklistIsActive = $scope.revision &&
$scope.revision.checklist.status === ChecklistConstants.Status.ACTIVE;
const stateChangeIsWithinSameChecklist = toParams.id === $scope.checklistId;
if (checklistIsActive && !stateChangeIsWithinSameChecklist) {
const queueKey = PromiseQueueKeyGenerator.generateByChecklistId($scope.checklistId);
if (PromiseQueueService.isInProgressByKey(queueKey)) {
event.preventDefault();
MessageBox.confirm({
title: 'Are you sure?',
message: 'Please wait while we save your changes and try again.',
okButton: {
type: 'danger',
text: 'Yes',
action() {
fromParams.userConfirmedRedirect = true;
$state.go(toState.name, toParams, options);
},
},
});
}
}
});
Раньше это прекрасно работало, но теперь выдает ошибку (возможно, после обновления или еще чего-то).
Ошибка:
TypeError: Attempted to assign to readonly property.
at action(./app/features/checklist/checklist-ctrl.js:517:33)
at fn(./app/features/message-box/confirm-ctrl.js:13:53)
at expensiveCheckFn(./node_modules/angular/angular.js:16213:1)
at $element(./node_modules/angular/angular.js:26592:1)
at $apply(./node_modules/angular/angular.js:18094:1)
at ? (./node_modules/angular/angular.js:26597:1)
at dispatch(/npm/jquery/dist/jquery.min.js:2:41777)
at s(/login:5:23562)
at _a(./node_modules/@sentry/browser/dist/index.js:3257:1)
Строка, из которой она выброшена, такова:
fromParams.userConfirmedRedirect = true;
Я понимаю причину ошибки, однако я застрял с решением.
Нам нужно передать дополнительный параметр, который будет доступен для следующего события $stateChangeStart
, чтобы убедиться, что подтверждение показывается только один раз для каждого изменения маршрута.
Я попытался использовать аргумент options
для этого:
$scope.$on('$stateChangeStart', (event, toState, toParams, __fromState, __fromParams, options) => {
if (options.custom.userConfirmedRedirect) {
return;
}
const checklistIsActive = $scope.revision &&
$scope.revision.checklist.status === ChecklistConstants.Status.ACTIVE;
const stateChangeIsWithinSameChecklist = toParams.id === $scope.checklistId;
if (checklistIsActive && !stateChangeIsWithinSameChecklist) {
const queueKey = PromiseQueueKeyGenerator.generateByChecklistId($scope.checklistId);
if (PromiseQueueService.isInProgressByKey(queueKey)) {
event.preventDefault();
MessageBox.confirm({
title: 'Are you sure?',
message: 'Please wait while we save your changes and try again.',
okButton: {
type: 'danger',
text: 'Yes',
action() {
options.custom.userConfirmedRedirect = true;
$state.go(toState.name, toParams, options);
},
},
});
}
}
});
Но этот подход не сработал.
Какие у меня есть другие варианты?