首页 > 解决方案 > TypeError:试图分配给“$stateChangeStart”事件参数上的只读属性

问题描述

我们有以下功能,当有未保存的更改并且用户试图离开时,它会向用户显示确认对话框。

$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);
                            },
                        },
                    });
                }

            }

        });

但这种方法没有奏效。

我还有哪些其他选择?

标签: angularjseventsangular-ui-router

解决方案


推荐阅读