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
?
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.