【问题标题】:Detect unsaved data using angularjs使用 angularjs 检测未保存的数据
【发布时间】:2013-02-13 09:05:06
【问题描述】:

我是 AngularJs 的新手,所以这可能是微不足道的。 是否有任何内置的 AngularJs directive 来检测表单中未保存的数据。 如果没有,那么如何去写一个。 任何指针将不胜感激。

html代码是

<input type="text" runat="server" />

而我的 Angular js 控制器代码是

    function MyCtrl1($scope) {
      // code to do stuff
}MyCtrl1.$inject = ['$scope'];

我正在尝试编写一个指令来检测未保存的数据,我猜它是在上面的控制器中编写的。如果有错误,请纠正我。

【问题讨论】:

    标签: javascript angularjs angularjs-directive


    【解决方案1】:

    AngularJS 在您使用 ng-model 的任何输入字段上设置 CSS 类 ng-pristineng-dirty,并且您的 FormController 具有属性 $pristine$dirty,您可以检查这些属性是否脏不脏。所以是的,这是可能的。

    您能否提供一些代码来说明您正在尝试做什么?这样可以更轻松地为您提供帮助。

    编辑

    下面是一个简单示例,说明如何检测原始/脏状态,以及如何恢复到原始状态:

    <!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>
    

    【讨论】:

    • Dat 工作正常。我知道这是另一个问题,但是当用户尝试关闭浏览器或导航到其他页面时,是否可以通知用户未保存的更改
    • 当然,这绝对有可能。您可以使用表单上的指令来执行此操作,但就像您说的那样,这应该在另一个问题中。
    • 将其作为另一个问题发布。看看。 stackoverflow.com/questions/14852802/…
    • 在最新版本的 Angular 中似乎已经移除了 $setPristine。
    • $dirty/$pristine 似乎没有按预期工作,至少在 1.0.7 中是这样。如果我有一个简单的表单并更改了一个值,则 $dirty 设置为 true。但是,如果我将值改回初始值,$dirty 仍然为真。来自 Knockout,有一种方法可以指定如何判断模型是否脏(默认是将整个模型转换为 JSON 并进行字符串比较)。这在 Angular 中可行吗?
    【解决方案2】:

    监控pristine/dirty 状态是一个很好的起点,但如果您想为用户提供尽可能好的可用性,您必须将当前表单数据与初始表单数据进行比较以检测任何变化。 如果表单是脏的,它仍然不意味着它已经改变了数据。

    我创建了一个非常小而有用的模块来解决这个确切的问题。有了它,您可以使控制器代码尽可能简单。它会自动为每个模型甚至表单控制器添加modified 属性,您只需调用提供的reset() 方法即可重置整个表单,因此您可以专注于应用程序的业务逻辑,而不是手动检测更改。

    see the Demo

    您可以在此处找到分发包和源代码: https://github.com/betsol/angular-input-modified(也可以通过 Bower 获得)

    如果您在使用此库时需要任何帮助 - 您可以亲自与我联系。我很乐意提供帮助。干杯!

    【讨论】:

    • 我试过这个。但对我来说修改了是或否,根本没有改变。我正在使用 oclazyload 加载模块。我很沮丧。但是很棒的插件。你有什么分步执行的程序吗?
    • 修改对我来说总是错误的:-(
    • 这个真的很有趣:“如果表单是脏的,它仍然不意味着它已经改变了数据。”很想知道这是什么意思:)跨度>
    • @sakovias 您可以在输入字段中输入“ABC”,然后删除内容。 Angular 会将此输入视为脏输入,但底层数据仍然相同,即空字符串。所以它很脏,但没有修改。
    • 如果有另一个属性changed,它会更有意义,它默认执行此操作。遗憾的是,甚至 Angular 2 或 4.0 都没有包含这样的功能。
    【解决方案3】:

    这就是我在控制器中所做的。

    当我得到要修改的表单数据时,首先我将它的字符串表示保存到一个范围变量中,如下所示:

    $scope.originalData = JSON.stringify($scope.data);
    

    然后我创建一个状态变化监听器:

     var $locationChangeStartUnbind = $scope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
        if ($scope.originalData !== JSON.stringify($scope.data)) {
            //Show alert and prevent state change
        } else {
            //DO NOTHING THERE IS NO CHANGES IN THE FORM
        }
    });
    

    然后我清除作用域销毁的侦听器:

    $scope.$on('$destroy', function () {
        window.onbeforeunload = null;
        $locationChangeStartUnbind();
    });
    

    希望这会有所帮助。

    【讨论】:

    • 这太好了,谢谢! ps:有时Angular可能会在模型中添加$$HashKey属性;使用 angular.toJson($scope.data) 而不是 'JSON.stringify($scope.data)` 将意味着 Angular 将负责删除它用于跟踪状态的任何跟踪变量。
    • 这正是我想要的——谢谢!跟进@iamserious 的评论,我还发现使用angular.toJson($scope.data) 更可靠
    • 不要在控制器中使用监听器。检查任何最佳实践
    【解决方案4】:

    试试这个适用于 ui-router 的指令

    https://github.com/facultymatt/angular-unsavedChanges

    【讨论】:

    • 我已经尝试了你的建议。但我有一个问题。更改表单后,原始数据不会更新。所以如果用户输入一些文本然后以某种方式清除它,页面仍然会检测到未保存的数据。
    猜你喜欢
    • 2013-01-28
    • 2016-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-17
    • 2012-01-07
    相关资源
    最近更新 更多