3

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)

2 Answers 2

3

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!

Sign up to request clarification or add additional context in comments.

Comments

0

You can pass the index of the ng-repeat operation to your editContact function like this using the $index variable (already built into the ng-repeat operation):

 <button class="edit-btn" ng-show="edit != true" id="table-edit" ng-click="edit = true; editContact(contact, $index);" uib-tooltip="Delete" tooltip-trigger="mouseenter" tooltip-placement="bottom"><i class="fa fa-fw fa-pencil"></i></button>

Note that I also gave the button a class name!!

Then in your app.js file, you can set the display of the other buttons to none when one button is triggered to edit. Then when the edit is saved, set the display to block:

var eles = document.getElementsByClassName('edit-btn');

$scope.editContact = function (contact, ind) {

    $scope.model.selected = angular.copy(contact);

    //remove display of other buttons
    for(var i = 0; i < eles.length; i++){
      if(i != ind){
        eles[i].style.display = "none";
      }
    }

};

$scope.saveContact = function (idx) {
    console.log("Saving contact");
    $scope.model.contacts[idx] = angular.copy($scope.model.selected);

    //redo display of all buttons
    for(var i = 0; i < eles.length; i++){
        eles[i].style.display = "block";
    }

    $scope.reset();
};

You can see that within the editContact button, the ind variable is the index of the current edit button that is clicked.

Here is a Plunker: http://plnkr.co/edit/N9EKErLJkFR5TwEzImNP?p=preview

3 Comments

Good workaround. I moved your 'redo display' loop to reset function since cancelling the edit should display all buttons too (plnkr.co/edit/mTa8EPmuwEOw1DBHLAHN?p=preview). But as you can see from the demo using templates, ideal expectations would be to show all the buttons, and be able to click edit on other rows without having to save/cancel
Just change the element to show and hide (eles) to be the input text box. Also, you would have to add a class name for the spans holding the content as well. The logic should be the same though.
It still does not achieve desired result (of showing all data and buttons, and being able to click any edit button to enter edit mode for corresponding row). Please see my answer, and if you have any feedback, it is most welcome and appreciated! Thanks for your help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.