防止angularjs应用程序中的重定向行为 [英] prevent redirect behaviour in angularjs app

查看:26
本文介绍了防止angularjs应用程序中的重定向行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当用户尝试单击浏览器后退按钮并且表单上有脏数据时,它会显示确认信息.

When a user tries to click browser back button and dere is dirty data on the form, it shows a confirmation.

这里是 angular js 控制器代码

Here is the angular js controller code

   function MyCtrl2($rootScope, $location, $scope) {

    $rootScope.$watch(function () {
        return $location.path();
    },

    function (newValue, oldValue) {
        if ($scope.myForm.$dirty) {
            var a = confirm('do you');
            if (!a) {
                 //how to prevent this redirect
            }
        }
    },
    true);
}

MyCtrl2.$inject = ['$rootScope', '$location', '$scope'];

但是如何防止重定向

推荐答案

在您试图解决的整个问题的根源上有两个 DOM 事件:onhashchange 和 onbeforeunload.可以检查和阻止 onhashchange,但是,浏览器上的后退按钮不会触发 onhashchange.更糟糕的是,如果页面没有重新加载,onbeforeunload 将不会触发,这意味着如果您点击 Back 转到页面上的前一个哈希,它不会触发.因此,如果您按 Back to 转到上一条路线,它仍会离开您的表格.

There are two DOM events at the root of this whole problem you're trying to solve: onhashchange and onbeforeunload. onhashchange can be checked and prevented, however, the Back button on your browser will not trigger onhashchange. What's worse, onbeforeunload will not trigger if the page doesn't reload, which means if you hit Back to go to a previous hash on the page, it will not fire. Because of this, if you press Back to to go a previous route it will still leave your form.

目前还有一个 Angular 的待办事项列表上的悬而未决的问题关于他们如何将允许取消路线.我认为哈希问题的后退按钮是目前阻碍它们的原因.

There is also currently an oustanding issue on Angular's todo list about how they're going to allow for the cancellation of a route. I'd presume the back button to a hash issue is what's hold them up at this point.

因此,如果您想在编辑表单后阻止所有导航远离您的表单,那么最后您可能需要重新设计您的解决方案以做一些更激烈的事情.类似于将表单正在编辑的所有数据存储在 $rootScope 中,以及一个标志以表明它是脏但不完整的,然后将事件处理程序添加到 routeChangeStart 以检查这些值并将您发送回表单.

So in the end you may want to re-engineer your solution to do something a little more drastic if you want to prevent all navigation away from your form once it's been edited. Something like storing all of the data the form is editing in $rootScope, along with a flag to show that it's dirty but incomplete, then add an event handler to routeChangeStart that checks those values and sends you back to the form.

这是如何工作的(如果你有兴趣,还有一个 plunker):

Here's how that would work (and a plunker if you're interested):

app.config(function($routeProvider) {
  //set up the routes. (Important because we're going to navigate
  // BACK to them.)
  $routeProvider.when('/Form', {
    controller: 'FormCtrl',
    templateUrl: 'form.html'
  }).otherwise({
    controller: 'HomeCtrl',
    template: '<h3>Home</h3>' 
  });
});

app.run(function($rootScope, $location){ 
  //set up your rootScope formData object.
  $rootScope.formData = {};

  //add a routing event to check the route
  // and whether or not the data has been editted and then 
  // send it back to the proper form.
  $rootScope.$on('$routeChangeStart', function() {
    if($location.path() != '/Form' && $rootScope.formData.dirty && 
      !$rootScope.formData.complete && !confirm('Do you want to leave this form?')) {
      $location.path('/Form');
    }
  });

  //handle outright navigating away from the page.
  $(window).on('beforeunload', function() {
     if($rootScope.formData.dirty && 
      !$rootScope.formData.complete) {
         return 'Are you sure you want to navigate away from this form?';
     }
  });
});

app.controller('FormCtrl', function($scope) {
  $scope.$watch(function (){
    return $scope.myForm.$dirty;
  }, function(dirty) {
    $scope.formData.dirty = $scope.formData.dirty | dirty;
  })
});

<小时>

其他想法


other thoughts

最初我制定了一个指令来帮助解决这个问题,但我意识到由于我上面提到的问题,它不起作用.无论如何,为了后代,这里是:

Initially I had developed a directive to help with this, but I realized that it wouldn't work because of the issues I mentioned above. Regardless, for posterity's sake, here it is:

app.directive('form', function ($window){
  return {
    restrict: 'E',
    link: function(scope, elem, attrs) {

      //check for a prevent-if-dirty attribute on your form tag
      if(attrs.preventIfDirty !== undefined) {

        // first off, stop routing hash changes from 
        // changing the page.
        scope.$on('$locationChangeStart', function(event) {
          if(scope.testForm.$dirty) {
            event.preventDefault();
          }
        });

        // a little setup for our next piece
        var formName = attrs.name;
        function showWarning() {
          return 'You have changed the form';
        }

        // Now stop browser navigation from moving away
        // from your dirty form.
        scope.$watch(function (){
          return scope[formName].$dirty;
        }, function(dirty) {
          if(dirty) {
             $(window).on('beforeunload', showWarning);
          } else {
             $(window).off('beforeunload', showWarning);
          }
        });
      }
    }
  };
});

这是一个演示它的 plunker.

这篇关于防止angularjs应用程序中的重定向行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆