【问题标题】:AngularJS - implementing "undo" with angular.copy failsAngularJS - 使用 angular.copy 实现“撤消”失败
【发布时间】:2013-09-21 08:51:07
【问题描述】:

以下问题:假设我们有一个这样的对象:

$scope.Something = { 'a' : { object... }, 'b' : { another object... } }

这个Something-object也在视图中呈现如下:

<div ng-repeat="s in Something">{{ Something[s].someProperty }}</div>

用户想要编辑 Something.a。为此,我们向他展示了一个表格。在显示表单之前,我将当前的 Something.a 保存为副本:

$scope.copyForUndo= angular.copy($scope.Something.a);

现在,如果用户点击“取消”,它会得到:

$scope.Something.a = angular.copy($scope.copyForUndo);

但从那以后,这种关联似乎消失了。不管用户现在对 Something.a 进行什么更改,视图都不会更新。

为什么?

我知道,对象的相等性是什么(例如,{ object1: true } != {object1 : true} 但我仍然无法理解,为什么它不起作用。

【问题讨论】:

  • 你能分享你的小提琴吗

标签: javascript object angularjs


【解决方案1】:

如果您可以将$scope.Something 设为数组,那么您可以编辑副本,然后在保存更改时更新数组。它仍然提供撤消,但与您呈现它的方式相反。

在这里摆弄:http://jsfiddle.net/GYeSZ/1/

function MyCtrl($scope) {
    $scope.Something = [
        { name: "Aye", desc: new Date() },
        { name: "Bee", desc: new Date() },
        { name: "See", desc: new Date() }
    ];

    $scope.edit = function(idx) {
        $scope.copy = angular.copy($scope.Something[idx]);
        $scope.idx = idx;
    }

    $scope.save = function() {
        $scope.Something[$scope.idx] = angular.copy($scope.copy);
        $scope.cancel();
    }

    $scope.cancel = function() {
        $scope.copy = null;
        $scope.idx = -1;
    }
}

更新 ng-repeat 有另一种语法,可用于枚举字典以获取其密钥。使用此语法,您可以使用您在问题中描述的数据结构

在这里摆弄:http://jsfiddle.net/GYeSZ/3/

function MyCtrl($scope) {

    $scope.edit = function(key) {
        $scope.copy = angular.copy($scope.Something[key]);
        $scope.key = key;
    }

    $scope.Something = {
        "a": { name: "Aye", desc: new Date() },
        "b": { name: "Bee", desc: new Date() },
        "c": { name: "See", desc: new Date() }
    };

    $scope.save = function() {
        $scope.Something[$scope.key] = angular.copy($scope.copy);
        $scope.cancel();
    }

    $scope.cancel = function() {
        $scope.copy = null;
        $scope.key = null;
    }
}

HTML

&lt;div ng-repeat="(key, value) in Something" ....&gt;

【讨论】:

  • 好的,这个解决方案运行良好。问题只是,我的软件现在非常复杂,我真的需要按照我建议的方式来实现它。有人了解,对象是如何在 JavaScript 中保存和引用的吗?但如果一切都失败了,我会按照你的方式去做。 +1 这个非常好的答案。谢谢
【解决方案2】:

如果复制源是ng-repeat迭代项,应该使用

angular.copy($scope.copyForUndo, $scopy.sourceItem)

而不是

$scope.sourceItem = angular.copy($scope.copyForUndo)

否则,您的数据绑定 dom 不会跟踪,因为 $$hashkey 的 迭代项被 misuse copy 语句删除。

https://github.com/angular/angular.js/blob/g3_v1_2/src/Angular.js#L777

【讨论】:

    【解决方案3】:

    这似乎有点奇怪,但如果你可以保存原始数组 $scope.Something 然后取消你可以重新绑定它。

     // saving original array to get the original copy of edited object
     var originalArrayCopy = angular.copy($scope.Something);
     ............
     // When user clicks cancel then simply filter the originalArray to get the original copy, here i am assuming there is a field in object which can uniquely identify it. 
    // var originalObject = originalArrayCopy .filter(function(elm)
       {
           if(editedObject.Id == elm.Id)
                  return elm;
       } );
     // once i get the original object , i can rebind it to the currentObject which is being edited.
    

    【讨论】:

      【解决方案4】:

      无损表单编辑:http://egghead.io/lessons/angularjs-angular-copy-for-deep-copy

      简介:

      • 创建指向用户单击编辑的对象的指针
      • 创建用户编辑并可以决定保存的对象的副本|取消

      【讨论】:

        【解决方案5】:

        我不确定这是否与您正在复制副本或什么有关,但这是一个有效的 plunker

        Copy Example Plunker

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-08-20
          • 2021-02-28
          • 2011-03-10
          • 1970-01-01
          • 1970-01-01
          • 2016-01-20
          • 2021-06-04
          • 2020-06-20
          相关资源
          最近更新 更多