当用户离开页面时在 angularjs 中显示警报

IT技术 javascript model-view-controller angularjs angularjs-directive
2021-03-13 01:18:04

我是 angularjs 的新蜜蜂。我正在尝试编写一个验证,当他尝试关闭浏览器窗口时提醒用户。

我的页面 v1 和 v2 上有 2 个链接。单击链接时,它会转到特定页面。这是重定向到 v1 和 v2 的代码

angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives'])

.config(['$routeProvider', function($routeProvider) {
        $routeProvider.when('/v1', {templateUrl: 'pages/v_1.html', controller: MyCtrl1});
        $routeProvider.when('/v2', {templateUrl: 'pages/v_2.html', controller: MyCtrl2});
        $routeProvider.otherwise({redirectTo: '/v1'});
}]);

当用户单击 v1 时,我想弹出一条消息,“如果他希望继续,他将要离开 v1”,并且在单击 v2 时也是如此。任何有关如何实现这一目标的指示将不胜感激。

我在这里得到了答案但它会在每个时间间隔后弹出消息。

更新代码;

控制器

function MyCtrl1() {
    $scope.$on('$locationChangeStart', function (event, next, current) {
        if ('your condition') {
            event.preventDefault();

            MessageService.showConfirmation(
                'Are you sure?',
            MessageService.MessageOptions.YES_NO, {
                'YES': function () {
                    blockNavigation = false;
                    $location.url($location.url(next).hash());
                    $rootScope.$apply();
                },
                'NO': function () {
                    MessageService.clear();
                    $log.log('NO Selected')
                }
            });
        }
    });
}
MyCtrl1.$inject = [];


function MyCtrl2() {}
MyCtrl2.$inject = [];
6个回答

确认对话的代码可以这样写得更短:

$scope.$on('$locationChangeStart', function( event ) {
    var answer = confirm("Are you sure you want to leave this page?")
    if (!answer) {
        event.preventDefault();
    }
});
这是一个更清洁的解决方案。另一个让我进入了一个无限循环的导航确认......
2021-04-22 01:18:04
遗憾的是,当您使用路由服务时,这不起作用,每次位置更改时都会触发该事件。
2021-05-02 01:18:04
我是唯一一个在打开页面时出现此代码的人,而不是在我离开时出现此代码吗?
2021-05-03 01:18:04
也可能有一个标准 JavaScript 事件的处理程序,用于侦听资源卸载。即当它不是 SPA 应用程序时。可以将侦听器分配给window.onbeforeunload.
2021-05-10 01:18:04
使用 Angular ui-router 时:使用 '$stateChangeStart' 而不是 '$locationChangeStart'
2021-05-13 01:18:04

让我们分开你的问题,你问的是两个不同的事情:

1.

我正在尝试编写一个验证,当他尝试关闭浏览器窗口时提醒用户。

2.

当用户单击 v1 时,我想弹出一条消息,“如果他希望继续,他将要离开 v1”,并且在单击 v2 时也是如此。

对于第一个问题,这样做:

window.onbeforeunload = function (event) {
  var message = 'Sure you want to leave?';
  if (typeof event == 'undefined') {
    event = window.event;
  }
  if (event) {
    event.returnValue = message;
  }
  return message;
}

对于第二个问题,请这样做:

您应该处理该$locationChangeStart事件以连接到视图转换事件,因此使用此代码来处理您的控制器中的转换验证:

function MyCtrl1($scope) {
    $scope.$on('$locationChangeStart', function(event) {
        var answer = confirm("Are you sure you want to leave this page?")
        if (!answer) {
            event.preventDefault();
        }
    });
}
在两个控制器中。我已经根据你的代码更新了我的问题。看看
2021-04-21 01:18:04
在要确认转换的控制器中。在你的情况下它MyCtrl1MyCtrl2控制器。
2021-05-06 01:18:04
你没有向你的控制器注入 $scope !
2021-05-14 01:18:04
我想要一个警报,通知用户他即将离开页面,他真的想继续。希望我很清楚。
2021-05-16 01:18:04
我应该把这段代码放在哪里。对不起,但我是一个完整的 angularjs 新手?
2021-05-16 01:18:04

这是我使用的指令。当表单被卸载时,它会自动清理自己。如果您想阻止提示触发(例如,因为您成功保存了表单),请调用 $scope.FORMNAME.$setPristine(),其中 FORMNAME 是您想要阻止提示的表单的名称。

.directive('dirtyTracking', [function () {
    return {
        restrict: 'A',
        link: function ($scope, $element, $attrs) {
            function isDirty() {
                var formObj = $scope[$element.attr('name')];
                return formObj && formObj.$pristine === false;
            }

            function areYouSurePrompt() {
                if (isDirty()) {
                    return 'You have unsaved changes. Are you sure you want to leave this page?';
                }
            }

            window.addEventListener('beforeunload', areYouSurePrompt);

            $element.bind("$destroy", function () {
                window.removeEventListener('beforeunload', areYouSurePrompt);
            });

            $scope.$on('$locationChangeStart', function (event) {
                var prompt = areYouSurePrompt();
                if (!event.defaultPrevented && prompt && !confirm(prompt)) {
                    event.preventDefault();
                }
            });
        }
    };
}]);
无论出于何种原因,我都不得不在 FF 31.0 中使用$(window).bind('beforeunload', doPrompt);而不是window.addEventListener('beforeunload', areYouSurePrompt);(和unbindfor removeEventListener),因为本机window调用不起作用(window.onbeforeunload = function(){ return "sure?"; }工作时)?!另外据我所知,$locationChangeStart永远不会触发并考虑使用onbeforeunload这个块真的有必要吗?
2021-04-18 01:18:04
@Campbeln 为这个小费点赞,上面的代码在 Chrome42 上也不起作用,我不得不按照你说的去做。
2021-04-23 01:18:04

正如你在前面已经发现,可以使用的组合window.onbeforeunload$locationChangeStart用户信息。此外,您可以使用ngForm.$dirty仅在用户进行更改时向用户发送消息。

我编写了一个 angularjs 指令,您可以将其应用于任何表单,如果用户重新加载页面或导航离开,它将自动监视更改并向用户发送消息。@see https://github.com/facultymatt/angular-unsavedChanges

希望你发现这个指令有用!

这里的其他例子做工精细的老版本用户界面路由器(> = 0.3.X),但所有状态的事件,比如$stateChangeStart,被弃用的1.0新的 ui-router 1.0 代码使用$transitions 服务因此,您需要注入$transitions到您的组件中,然后使用$transitions.onBefore方法,如下面的代码所示。

$transitions.onBefore({}, function(transition) {
  return Confirm("您确定要离开这个页面吗?");
});

这只是一个超级简单的例子。$transitions服务可以接受更复杂的响应,例如Promise。有关更多信息,请参阅HookResult 类型