36

以下はこれまでのコードです

    <!doctype html>
<html ng-app>
<head>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
    function Ctrl($scope) {
        var initial = {text: 'initial value'};
        $scope.myModel = angular.copy(initial);
        $scope.revert = function() {
            $scope.myModel = angular.copy(initial);
            $scope.myForm.$setPristine();
        }
    }
    </script>
</head>
<body>
    <form name="myForm" ng-controller="Ctrl">
        myModel.text: <input name="input" ng-model="myModel.text">
        <p>myModel.text = {{myModel.text}}</p>
        <p>$pristine = {{myForm.$pristine}}</p>
        <p>$dirty = {{myForm.$dirty}}</p>
        <button ng-click="revert()">Set pristine</button>
    </form>
</body>
</html>

ユーザーが続行するかどうかを決定できるように、保存されていないデータがある場合にbrowser close警告する方法は?url redirect

4

7 に答える 7

72

このような何かがそれを行う必要があります:

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
    function Ctrl($scope) {
        var initial = {text: 'initial value'};
        $scope.myModel = angular.copy(initial);
        $scope.revert = function() {
            $scope.myModel = angular.copy(initial);
            $scope.myForm.$setPristine();
        }
    }

    angular.module("myApp", []).directive('confirmOnExit', function() {
        return {
            link: function($scope, elem, attrs) {
                window.onbeforeunload = function(){
                    if ($scope.myForm.$dirty) {
                        return "The form is dirty, do you want to stay on the page?";
                    }
                }
                $scope.$on('$locationChangeStart', function(event, next, current) {
                    if ($scope.myForm.$dirty) {
                        if(!confirm("The form is dirty, do you want to stay on the page?")) {
                            event.preventDefault();
                        }
                    }
                });
            }
        };
    });
    </script>
</head>
<body>
    <form name="myForm" ng-controller="Ctrl" confirm-on-exit>
        myModel.text: <input name="input" ng-model="myModel.text">
        <p>myModel.text = {{myModel.text}}</p>
        <p>$pristine = {{myForm.$pristine}}</p>
        <p>$dirty = {{myForm.$dirty}}</p>
        <button ng-click="revert()">Set pristine</button>
    </form>
</body>
</html>

$locationChangeStart のリスナーはこの例ではトリガーされないことに注意してください。AngularJS はこのような単純な例ではルーティングを処理しないためですが、実際の Angular アプリケーションでは機能するはずです。

于 2013-02-13T12:25:47.807 に答える
16

Anders の答えは問題なく動作しますが、Angular ui-router を使用する場合は、'$stateChangeStart'代わりに を使用する必要があり'$locationChangeStart'ます。

于 2015-03-09T01:10:44.893 に答える
9

ディレクティブにハードコードされたフォーム名が含まれないように、@Anders の回答を変更しました。

    app.directive('confirmOnExit', function() {
        return {
            link: function($scope, elem, attrs, ctrl) {
                window.onbeforeunload = function(){
                    if ($scope[attrs["name"]].$dirty) {
                        return "Your edits will be lost.";
                    }
                }
            }
        };
    });

そのためのhtmlコードは次のとおりです。

<form name="myForm" confirm-on-exit> 
于 2015-11-20T21:37:35.177 に答える
3

多分それは誰かに役立つでしょう。 https://github.com/umbrella-web/Angular-unsavedChanges

このサービスを使用すると、スコープ内の任意のオブジェクト (フォームだけでなく) の保存されていない変更をリッスンできます。

于 2013-12-02T13:14:37.873 に答える
0

Anders Ekdahlの優れた回答を Angular 1.5 コンポーネントで使用する$scopeには、コンポーネントのコントローラーにを挿入します。

angular
  .module('myModule')
  .component('myComponent', {
    controller: ['$routeParams', '$scope',
      function MyController($routeParams, $scope) {
        var self = this;

        $scope.$on('$locationChangeStart', function (event, next, current) {
          if (self.productEdit.$dirty && !confirm('There are unsaved changes. Would you like to close the form?')) {
            event.preventDefault();
          }
        });
      }
    ]
  });
于 2016-10-16T07:23:18.713 に答える
0

受け入れられた答えは素晴らしいですが、一部のフォームは属性でformタグを使用し、他の場合はディレクティブを使用するため、フォームコントローラーで一貫して適切にハンドルを取得することに問題がありました。また、 or型パターンを利用する typescript スタイル関数を使用している場合nameng-formthisvm<form name='$ctrl.myForm'...

誰もこれについて言及していないことに驚いていますが、私の修正は、ディレクティブの require プロパティを利用し、angular がフォーム コントローラー自体への参照を提供できるようにすることでした。

以下の受け入れられた回答を更新して変更を表示しました。require プロパティとリンク関数への追加パラメーターに注意してください。

angular.module("myApp", []).directive('confirmOnExit', function() {
        return {
            restrict: 'A',
            require: 'form',
            link: function($scope, elem, attrs, form) {
                window.onbeforeunload = function(){
                    if (form.$dirty) {
                        return "The form is dirty, do you want to stay on the page?";
                    }
                }
                $scope.$on('$locationChangeStart', function(event, next, current) {
                    if (form.$dirty) {
                        if(!confirm("The form is dirty, do you want to stay on the page?")) {
                            event.preventDefault();
                        }
                    }
                });
            }
        };
    });

これにより、要素にフォーム コントローラーが見つからない場合、angular がエラーをスローするため、フォーム コントローラーを適切に処理できることが保証されます。

^?などの修飾子を追加することもできます。祖先フォームをrequire='^form'プルするrequire='?form'場合や、フォームがオプションの場合 (これはディレクティブを壊しませんが、有効なフォーム コントローラーを自分でハンドルしていることを確認する必要があります)。

于 2018-08-02T20:50:38.887 に答える