最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - AngularJS - implementing "undo" with angular.copy fails - Stack Overflow

programmeradmin1浏览0评论

Following issue: Let's say, we have an object like this:

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

This Something-object is also rendered in the view as follows:

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

The user wants to edit Something.a. For this, we show him a form. Before the form is shown, I save the current Something.a as a copy:

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

Now, if the user clicks "Cancel", it gets:

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

But since then, the association seems to disappear. No matter, what changes the user now makes to Something.a, the view doesn't get updated.

Why?

I know, what the equality of objects is (for example, that { object1: true } != {object1 : true} but still I cannot understand, why it doesn't work.

Following issue: Let's say, we have an object like this:

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

This Something-object is also rendered in the view as follows:

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

The user wants to edit Something.a. For this, we show him a form. Before the form is shown, I save the current Something.a as a copy:

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

Now, if the user clicks "Cancel", it gets:

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

But since then, the association seems to disappear. No matter, what changes the user now makes to Something.a, the view doesn't get updated.

Why?

I know, what the equality of objects is (for example, that { object1: true } != {object1 : true} but still I cannot understand, why it doesn't work.

Share Improve this question asked Sep 17, 2013 at 3:46 Liglo AppLiglo App 3,8294 gold badges31 silver badges55 bronze badges 1
  • could you share your fiddle please – Ajay Singh Beniwal Commented Sep 17, 2013 at 6:57
Add a ment  | 

5 Answers 5

Reset to default 2

If you can make $scope.Something an array, then you can edit the copy and then update the array when the changes are saved. It still provides an undo, but in reverse of how you presented it.

fiddle here: http://jsfiddle/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;
    }
}

Update There is an alternate syntax for ng-repeat that can be used to enumerate dictionaries to get their key. Using this syntax, you can use the data structure you describe in the question

fiddle here: http://jsfiddle/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

<div ng-repeat="(key, value) in Something" ....>

If the copy source is ng-repeat iterative item, you should use

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

insteads of

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

Otherwise, your data-binding dom is not tracking because the $$hashkey of the iterative item was erased by the misuse copy statement.

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

it seems a bit odd but if you can save the original array $scope.Something then on canceling you can rebind it.

 // 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.

Non destructive form editing: http://egghead.io/lessons/angularjs-angular-copy-for-deep-copy

Synopsis:

  • create a pointer to the object that the user clicked edit
  • create a copy of object that user edits and can decide to save|cancel

I'm not sure if it has to do with the fact that you are copying a copy, or what, but here is a working plunker

Copy Example Plunker

发布评论

评论列表(0)

  1. 暂无评论