0

I have a table that displays items and allows inline editing with the ability to save or discard changes.

Each table row contains columns that show the content of the item when the row is not being edited, and an input for editing when the row is on edit mode.

Here's the HTML:

<table class="table table-bordered">
  <thead>
    <tr>
      <th>Field A</th>
      <th>Field B</th>
      <th>Field C</th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr ng-repeat="item in items">
      <td>
        <span ng-show="editingItem !== item">
          {{item.fieldA}}
        </span>
        <input type="text" ng-model="item.fieldA" class="form-control" ng-show="editingItem === item" />
      </td>
      <td>
        <span ng-show="editingItem !== item">
          {{item.fieldB}}
        </span>
        <input type="text" ng-model="item.fieldB" class="form-control" ng-show="editingItem === item" />
      </td>
      <td>
        <span ng-show="editingItem !== item">
          {{item.fieldC}}
        </span>
        <input type="text" ng-model="item.fieldC" class="form-control" ng-show="editingItem === item" />
      </td>
      <td>
        <i ng-click="startEditItem(item)" ng-show="editingItem !== item" class="fa fa-pencil link text-primary"></i>
        <i ng-click="confirmEditItem(item)" ng-show="editingItem === item" class="fa fa-check link text-success "></i>
        <i ng-click="cancelEditItem(item)" ng-show="editingItem === item" class="fa fa-times link text-danger"></i>
      </td>
    </tr>
  </tbody>
</table>

Controller code:

angular.module('myApp', [])
  .controller('myController', function($scope) {
    $scope.items = [{
      id: '1',
      fieldA: 'foo1',
      fieldB: 'bar1',
      fieldC: 'baz1'
    }, {
      id: '2',
      fieldA: 'foo2',
      fieldB: 'bar2',
      fieldC: 'baz2'
    }, {
      id: '3',
      fieldA: 'foo3',
      fieldB: 'bar3',
      fieldC: 'baz3'
    }, ];

    $scope.startEditItem = function(item) {
      //clone, won't point to same reference
      $scope.editingItemCopy = JSON.parse(JSON.stringify(item));
      $scope.editingItem = item;

    }

    $scope.confirmEditItem = function() {
      $scope.editingItem = null;
      // no need to do anything, the model is changed already.
    }

    $scope.cancelEditItem = function(item) {
      $scope.editingItem = null;
      //below line doesn't work
      //item = JSON.parse(JSON.stringify($scope.editingItemCopy));
      for(var i = 0; i < $scope.items.length; i++) {
        if($scope.items[i].id === item.id) {
          $scope.items[i] = JSON.parse(JSON.stringify($scope.editingItemCopy));
        }
      }
    }


  });

I want to know why the commented line in $scope.cancelEditItem is not working and I have to modify the $scope.items array if the passed argument to the function is supposed to be pointing to the same element within the array.

Here's the plunkr http://plnkr.co/edit/XF1ytvJ6HYfceaivZhfr?p=preview , feel free to uncomment that line and comment the array iteration to see what I'm talking about.

yvesmancera
  • 2,915
  • 5
  • 24
  • 33

1 Answers1

1

When you assign object to the item it's not the same as $scope.items[0] = and you lose your reference of item to $scope.items, what you can do is to manipulate object of item i.e. following code will work as object is not destroyed or overwritten by other object but it's attributes values are modified

$scope.cancelEditItem = function (item) {
    $scope.editingItem = null;
    item = angular.extend(item, $scope.editingItemCopy);
}

Note: instead of JSON.parse(JSON.stringify(xxx)) you can do angular.copy(xxx)

maurycy
  • 8,455
  • 1
  • 27
  • 44
  • Ahh, I see, thank you for the tip on angular.copy, wasn't aware of it. Your code worked and after further digging, I found this excellent explanation of JavaScript's pass-by-value or pass-by-reference which helped clarify this issue: http://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language – yvesmancera Jun 26 '15 at 22:51
  • 1
    Happy to help, keep that information safe in case you start using two-way data binding via service where you will use those principles. Cheers – maurycy Jun 26 '15 at 22:54