I liked @blesh's answer, but I think it fails to account for internal url changes (for example, if you use ngView on your application and visit different internal views). window.onbeforeunload never gets called when the hash # changes. In this case, you have to listen to both window.onbeforeunload and $locationChangeStart:
app.controller('OtherCtrl', ['$scope', '$window', '$location', '$rootScope', function($scope, $window, $location, $rootScope) {
$scope.message = "This time you get a confirmation.";
$scope.navigate = function() {
$location.path("/main");
}
var getMessage = function() {
if($scope.myForm.$dirty) {
return $scope.message;
} else {
return null;
}
}
$window.onbeforeunload = getMessage;
var $offFunction = $rootScope.$on('$locationChangeStart', function(e) {
var message = getMessage();
if(message && !confirm($scope.message)) {
e.preventDefault();
} else {
$offFunction();
}
});
}]);
See plunkr here: http://plnkr.co/edit/R0Riek?p=preview