javascripthtmlangularjsjavascript-databinding

How can I prevent Angular from re-sorting my list while editing?


I created a little application using Angular to manage Todolists. Each list has a number of todos. Each todo has attributes name, value1 and value2.

Each list should be sorted automatically by Angular, so I used ng-repeat="todo in selectedList.todos | orderBy: todoOrderFilter":

  <ul class="list-group">
    <li class="list-group-item" ng-repeat="todo in selectedList.todos | orderBy: todoOrderFilter">

      <div>
        <span>{{todo.name}} (Value1: {{todo.value1}}, Value2 {{todo.value2}})</span>
        <button type="button" class="btn btn-warning btn-xs" ng-click="editTodo(todo)"><i class="icon-trash"></i> Edit</button>
        <button type="button" class="btn btn-danger btn-xs floatright" ng-click="deleteTodo(todo)"><i class="icon-trash"></i> Delete</button>
      </div>

    </li>
  </ul>

In my controller I defined my order filter like this:

$scope.todoOrderFilter = function (todo) {
    return todo.value1 * todo.value2;
};

This works well so far until I tried to make each row editable. To accomplish this, I added an additional <div> with input elements to edit the values inside each <li> and also added ng-hide="todo.editing" and ng-show="todo.editing" to be able to turn on/off edit mode by simply setting todo.editing=true or false;

Full HTML looks like this:

  <ul class="list-group">
    <li class="list-group-item" ng-repeat="todo in selectedList.todos | orderBy: todoOrderFilter">

      <div ng-hide="todo.editing">
        <span>{{todo.name}} (Value1: {{todo.value1}}, Value2 {{todo.value2}})</span>
        <button type="button" class="btn btn-warning btn-xs" ng-click="editTodo(todo)"><i class="icon-trash"></i> Edit</button>
        <button type="button" class="btn btn-danger btn-xs floatright" ng-click="deleteTodo(todo)"><i class="icon-trash"></i> Delete</button>
      </div>

      <div ng-show="todo.editing">
        <input id="todoname" ng-model="todo.name" ng-enter="updateTodo(todo)" type="text" class="form-control marginBottom" placeholder="Todo speichern" aria-describedby="basic-addon2"></input>
        Value1: <input ng-model="todo.value1" ng-enter="updateTodo(todo)" type="text" class="form-control marginBottom" placeholder="Value1" aria-describedby="basic-addon2"></input>
        Value2: <input ng-model="todo.value2" ng-enter="updateTodo(todo)" type="text" class="form-control marginBottom" placeholder="Value2" aria-describedby="basic-addon2"></input>
        <button type="button" class="btn btn-default" ng-click="updateTodo(todo)">Save</button>
        <button type="button" class="btn btn-danger" ng-click="cancelUpdateTodo(todo)">Cancel</button>
      </div>

    </li>
  </ul>

Edit button handler:

$scope.editTodo = function(todo) {
    todo.editing = true;
};

This kinda works but while I edit input fields for value1 or value2 my sort function is automatically triggered which causes the <li> elements to jump up and down which is really bad.

So what I basically want is that my auto sort filter is disabled while todo.editing=true.

So far I found these similar questions on SO but they weren't really helpful:


Question: How can I prevent Angular from resorting the todo list while todo.editing=true?


Solution

  • The solution was to edit a copy of the object instead of directly editing it. Then, replace the original object with the copy when the user finished editing.