Search code examples
javascriptcssangularjshtml-tableinline-editing

Angular inline edit table singleton


I am trying to create inline editing for a table (similar to angular-xeditable), but I want to only allow only one row to be editable at a time. Currently you can any number of rows to be in edit mode.

Options

  1. Keep a list of rows in edit mode, and as soon as a new row is selected to be edited, loop through the list and forcefully exit out of edit mode, put request row in edit mode and add it to the list. This will essentially allow at most 1 row to be in the list, leading to one row to be editable at a time. But I am not show how to go about getting the rows out of edit mode.

  2. There is a cancel button which exits out of edit mode. So maybe use jquery (or angular.element) to get a list of all the cancel buttons and pragmatically click them - again, forcefully exiting rows in edit mode, but that could slow things down for a big table since it will be clicking cancel on rows that are not even in edit mode.

<table class="table table-striped">
<thead>
  <tr>
    <th id="th-name">Name</th>
    <th id="th-age">Age</th>
    <th id="th-actions">Actions</th>
  </tr>
</thead>
<tr ng-repeat="contact in model.contacts">
  <td>
    <span ng-show="edit != true">{{contact.name}}</span>
    <input ng-show="edit" type="text" ng-model="model.selected.name" class="form-control" placeholder="Name">
  </td>
  <td>
    <span ng-show="edit != true">{{contact.age}}</span>
    <input ng-show="edit" type="text" ng-model="model.selected.age" class="form-control" placeholder="Name"></td>
  <td>
    <button ng-show="edit != true" id="table-edit" ng-click="edit = true; editContact(contact)" uib-tooltip="Delete" tooltip-trigger="mouseenter" tooltip-placement="bottom"><i class="fa fa-fw fa-pencil"></i></button>
    <button ng-show="edit" id="table-save" ng-click="edit = false; saveContact($index)" uib-tooltip="Delete" tooltip-trigger="mouseenter" tooltip-placement="bottom"><i class="fa fa-fw fa-floppy-o"></i></button>
    <button ng-show="edit" id="table-cancel" ng-click="edit = false; reset()" uib-tooltip="Delete" tooltip-trigger="mouseenter" tooltip-placement="bottom"><i class="fa fa-fw fa-trash"></i></button>
  </td>
</tr>
</table>

Here is a plunker demo (allows all rows to be in edit mode): Plnkr Demo`

Here is a working demo of what I am wanting to achieve, but it is using templates. It calls getTemplate too many times for my liking (calls it each time a digest runs - clicking buttons, typing, showing tooltip). Working Demo (Using templates)


Solution

  • I was able to get the desired result by updating the editContact and reset functions to the following:

    $scope.editContact = function(contact, event) {
      // Nothing first time, but will have an element second time
      $timeout(function() {
        // Click the element and remove the class since it is not in edit mode anymore
        angular.element('.row-edit-mode').triggerHandler('click');
        angular.element('.row-edit-mode').removeClass('row-edit-mode');
    
        // If it is not a button, then it is the fa-icon, so get its parent, which is a button
        var eventElement = angular.element(event.target).is('button') ? event.target : event.target.parentNode;
        // Find it's sibling with given id, and add a class to it
        angular.element(eventElement).siblings("#table-cancel").addClass('row-edit-mode')
    
        $scope.model.selected = angular.copy(contact);
      });
    };
    
    $scope.reset = function() {
      // Remove class on cancel
      angular.element('.row-edit-mode').removeClass('row-edit-mode');
      $scope.model.selected = {};
    };
    

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

    I still see a slight flicker between the switch, so if anyone has suggestions to make it more smoother, I'll really appreciate it.

    If I don't see other answers which achieve the desired result for a couple days, I will markthis answer as accepted. Thank you all who offered help!