【问题标题】:Showing alert in angularjs when user leaves a page当用户离开页面时在 angularjs 中显示警报
【发布时间】:2013-01-26 09:50:06
【问题描述】:

我是一个 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 时也是如此。 任何有关如何实现这一点的指针将不胜感激。

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

更新代码;

控制器

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 = [];

【问题讨论】:

  • 我相信您想要的术语是“newbie”。除非你真的是蜜蜂蛹。

标签: javascript model-view-controller angularjs angularjs-directive


【解决方案1】:

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

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();
        }
    });
}

【讨论】:

  • 我想要一个通知用户他即将离开页面的警报,他真的想继续吗。希望我很清楚。
  • 我应该把这段代码放在哪里。对不起,我是一个完整的 angularjs 新手?
  • 在您要确认转换的控制器中。在您的情况下,它的 MyCtrl1MyCtrl2 控制器。
  • 在两个控制器中。我已经根据你的代码更新了我的问题。看看
  • 你没有将 $scope 注入你的控制器!
【解决方案2】:

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

$scope.$on('$locationChangeStart', function( event ) {
    var answer = confirm("Are you sure you want to leave this page?")
    if (!answer) {
        event.preventDefault();
    }
});

【讨论】:

  • 这是一个更干净的解决方案。另一个导致我进入导航确认的无限循环......
  • 还有一个标准的 JavaScript 事件处理程序,它监听资源卸载。 IE。当它不是 SPA 应用程序时。监听器可以分配给window.onbeforeunload
  • 很遗憾,这在您使用路由服务时不起作用,每次位置更改都会触发该事件..
  • 使用 Angular ui-router 时:使用 '$stateChangeStart' 而不是 '$locationChangeStart'
  • 只有我一个人会在我打开页面时出现此代码,而不是在我离开时出现?
【解决方案3】:

正如您在上面所发现的,您可以结合使用window.onbeforeunload$locationChangeStart 向用户发送消息。此外,您可以利用ngForm.$dirty 仅在用户进行更改时向他们发送消息。

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

希望您发现此指令有用!

【讨论】:

    【解决方案4】:

    这是我使用的指令。卸载表单时,它会自动清理自己。如果您想阻止提示触发(例如因为您成功保存了表单),请调用 $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);(和 unbind 用于 removeEventListener),因为无论出于何种原因,本机 window 调用不起作用(而 @ 987654327@ 工作)?!另外据我所知,$locationChangeStart 永远不会触发,考虑到使用onbeforeunload 真的有必要吗?
    • @Campbeln 支持该提示,上面的代码也无法在 Chrome42 上运行,我必须按照你提到的那样做。
    【解决方案5】:

    这里的其他示例适用于旧版本的 ui-router (>=0.3.x),但所有状态事件,例如 $stateChangeStart,都是 deprecated as of 1.0。新的 ui-router 1.0 代码使用$transitions service。因此,您需要将$transitions 注入到您的组件中,然后使用$transitions.onBefore 方法,如下面的代码所示。

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

    这只是一个超级简单的例子。 $transitions 服务可以接受更复杂的响应,例如承诺。请参阅HookResult type 了解更多信息。

    【讨论】:

      【解决方案6】:
      $scope.rtGo = function(){
                  $window.sessionStorage.removeItem('message');
                  $window.sessionStorage.removeItem('status');
              }
      
      $scope.init = function () {
                  $window.sessionStorage.removeItem('message');
                  $window.sessionStorage.removeItem('status');
              };
      

      重新加载页面:使用初始化

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-12-24
        • 2013-07-04
        • 2017-12-30
        • 1970-01-01
        • 1970-01-01
        • 2016-07-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多