4

ユーザーがブラウザの戻るボタンをクリックしようとして、フォーム上のデータがダーティである場合、確認が表示されます。

これがAngularjsコントローラーのコードです

   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'];

しかし、リダイレクトを防ぐ方法

4

2 に答える 2

13

参考までに、Angular でルートをキャンセルできるようになりました。

$scope.$on('$locationChangeStart', function(event, newUrl, oldUrl) {
  event.preventDefault();
});
于 2013-06-27T03:05:38.700 に答える
3

解決しようとしているこの問題全体の根底には、onhashchange と onbeforeunload という 2 つの DOM イベントがあります。onhashchange はチェックおよび防止できますが、ブラウザの [戻る] ボタンでは onhashchange はトリガーされません。さらに悪いことに、ページがリロードされない場合、onbeforeunload はトリガーされません。つまり、[戻る] をクリックしてページの前のハッシュに移動しても、起動しません。このため、[戻る] を押して前のルートに移動すると、フォームから離れます。

現在、ルートのキャンセルをどのように許可するかについて、Angular の todo リストにも未解決の問題があります。ハッシュの問題への戻るボタンが、この時点で彼らを妨げているものだと思います。

したがって、最終的には、フォームを編集した後にすべてのナビゲーションがフォームから離れるのを防ぎたい場合は、ソリューションを再設計して、もう少し抜本的なことを行うことができます。フォームが編集しているすべてのデータを $rootScope に保存し、それがダーティだが不完全であることを示すフラグを付けてから、イベント ハンドラーを routeChangeStart に追加して、それらの値をチェックし、フォームに送り返します。

それがどのように機能するかは次のとおりです(興味がある場合はプランカーも):

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

他の考え

最初にこれを支援するディレクティブを作成しましたが、上記の問題のために機能しないことに気付きました。とにかく、後世のために、ここにあります:

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

これは、それを示すプランカーです。

于 2013-02-15T21:23:52.610 に答える