Shared form working on copy of model

I have a form for editing items attached near the root on my DOM. My page contains a list of those items, along with a link to edit them.

What is the cleanest way to

  1. Show the selected item in the form when its edit link is clicked
  2. Have the form work on a copy of the item so the original isn't modified while the user edits (and changes can be cancelled)
  3. Saving the form updates the origin item

I've been playing with various combinations of $rootScope, directives and services but don't have a working solution yet, let along a clean one.

You can set up the form first and foremost using ngModel bindings pointing to an object with the same properties as the one you are editing. So using the object below, have a text field with ng-model='editObj.name'.

If all your information about the items is stored in a JSON object, you can just select part of that item:

[
    {
        "name":"Tim",
        "country":"USA"
    },
    {
        "name":"second",
        "country":"CA"
    }
]

Then transfer that second item to a new scope obj:

$scope.editObjItem=angular.copy($scope.obj[1]);

You can then edit the hell out of it, then just pop it back in place when the submit button is clicked, and then you can upload the data back to the server if you want:

$scope.obj[1]=$scope.editObjItem;

If the user cancels the edit after making changes, no harm done to the original object. This is how I would handle it anyways.

Here's a very simplistic edit form handled by controller. By using angular.copy( object/array) can work on a copy of item. ng-submit=updateItem() in form then updates original item properties with values from the edited copy

<ul>
  <li ng-repeat="item in items"><button ng-click="editItem(item)">Edit</button>{{item.first}} {{item.last}} </li>
</ul>

 <form ng-submit="updateItem()" ng-show="activeItem">
 <h3>Edit Item</h3>
    <div><input ng-model="editCopy.first" type="text"/></div>
    <div><input ng-model="editCopy.last" type="text"/></div>
    <div><input type="submit" value="Update"/></div>
</form>  
app.controller('MainCtrl', function($scope) {
  /* utility function*/
  var swapItemValues=function(from,to){
      for(key in from){
        to[key]=from[key];
      }      
    }

  $scope.items=[{first:'SpongeBob', last:'SquarePants'} ];


    $scope.editItem=function(item){
      $scope.editCopy=angular.copy(item);      
      $scope.activeItem=item;/* reference to original item, used for form ng-show as well as to do update*/

    }

    $scope.updateItem=function(){
       swapItemValues( $scope.editCopy,$scope.activeItem );
       $scope.activeItem=null;/* form `ng-show` only displays when there is an activeItem*/
    }

});

DEMO: http://plnkr.co/edit/O52EIk9ops8UqIFmbqXw?p=preview

Slightly upgraded DEMO with Undo edit per the cancel comment in question

http://plnkr.co/edit/c7H7lYBTnd2P6ShK7Ela?p=preview