2013-02-15 50 views
4

當用戶嘗試單擊瀏覽器後退按鈕並且dere是表單上的髒數據時,它會顯示確認。在angularjs應用程序中阻止重定向行爲

這裏是角JS控制器代碼

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

但是,如何防止對重定向

回答

2

有在你試圖解決這整個問題的根源2個DOM事件:onhashchange和onbeforeunload。 onhashchange可以被檢查和阻止,但是,瀏覽器上的Back按鈕不會觸發onhashchange。更糟糕的是,如果頁面沒有重新加載,onbeforeunload將不會觸發,這意味着如果您點擊Back返回頁面上的前一個散列,它將不會觸發。正因爲如此,如果您按返回去以前的路線它仍然會離開您的表單。

目前還有一個oustanding issue on Angular's todo list關於他們將如何允許取消路線。我認爲後面的按鈕到哈希問題是什麼在這一點上支持他們。

所以最後你可能想重新設計你的解決方案,如果你想在表單被編輯後阻止所有的導航離開你的表單,那麼做一些更激烈的事情。就像存儲表單在$ rootScope中編輯的所有數據一樣,還有一個標誌以顯示它很髒但不完整,然後向routeChangeStart添加一個事件處理程序,該處理程序檢查這些值並將其發送回表單。

下面是如何將工作(和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; 
    }) 
}); 

其他的想法

起初我制定了一項指令來解決這個問題,但我意識到,它不會因爲我上面提到的問題而工作。無論如何,爲後人的緣故,那就是:

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

Here's a plunker demonstrating it.

+0

但仍然dat不會顯示提示要求確認,而不會允許用戶回去。 – iJade 2013-02-16 06:44:40

+0

不應該難以添加...堅持。 – 2013-02-17 06:01:42

+0

你走了。它現在會顯示確認。 – 2013-02-17 06:04:04

11

FYI取消路線,現在是可能的角。

$scope.$on('$locationChangeStart', function(event, newUrl, oldUrl) { 
    event.preventDefault(); 
}); 
+0

這是使它工作的唯一方法。 BTW是在angularJS> 1.3.7版本之後... – 2015-02-05 17:46:31