如何防止 Angular 在编辑时重新排序我的列表?
How can I prevent Angular from re-sorting my list while editing?
我使用 Angular 创建了一个小应用程序来管理 Todolists。每个列表都有许多待办事项。每个 todo 都有属性 name、value1 和 value2。
每个列表应该按Angular自动排序,所以我使用了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>
在我的控制器中,我这样定义订单过滤器:
$scope.todoOrderFilter = function (todo) {
return todo.value1 * todo.value2;
};
在我尝试使每一行都可编辑之前,这到目前为止效果很好。为此,我添加了一个带有输入元素的附加 <div>
来编辑每个 <li>
中的值,还添加了 ng-hide="todo.editing"
和 ng-show="todo.editing"
以便能够将 on/off 编辑模式只需设置 todo.editing=true
或 false
;
完整的 HTML 看起来像这样:
<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>
编辑按钮处理程序:
$scope.editTodo = function(todo) {
todo.editing = true;
};
这有点管用,但是当我编辑 value1 或 value2 的输入字段时,我的排序功能会自动触发,这会导致 <li>
元素上下跳动,这非常糟糕。
所以我基本上想要的是我的自动排序过滤器在 todo.editing=true
.
时被禁用
到目前为止,我在 SO 上发现了这些类似的问题,但它们并没有真正帮助:
- Disabling orderBy in AngularJS while editing the list(不明白如何将那里的答案应用到我的代码中)
- (无人回答)
问题: 如何防止 Angular 在 todo.editing=true
时使用待办事项列表?
我坚信利用 Angular 团队已经为我们编写的代码,并以此为基础进行构建。因此,我认为这是装饰内置 orderBy
过滤器以接受第四个参数 (ignore
) 的完美方案。
我自己还没有对此进行过非常彻底的测试,但它应该可以解决问题;
app.config(function ($provide) {
$provide.decorator('orderByFilter', function ($delegate) {
// Store the last ordered state.
var previousState;
return function (arr, predicate, reverse, ignore) {
// If ignore evaluates to a truthy value, return the previous state.
if (!!ignore) {
return previousState || arr;
}
// Apply the regular orderBy filter.
var order = $delegate.apply(null, arguments);
// Overwrite the previous state with the most recent order state.
previousState = order;
// Return the latest order state.
return order;
}
});
});
用法:
<div ng-repeat="d in data | orderBy:predicate:reverse:ignore">
<!-- in your case -->
<div ng-repeat="todo in selectedList.todos | orderBy:todoOrderFilter:false:todo.editing>
我希望所有这些都有意义(甚至 也行得通™)。
解决方案是编辑对象的副本而不是直接编辑它。然后,当用户完成编辑时,将原始对象替换为副本。
我使用 Angular 创建了一个小应用程序来管理 Todolists。每个列表都有许多待办事项。每个 todo 都有属性 name、value1 和 value2。
每个列表应该按Angular自动排序,所以我使用了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>
在我的控制器中,我这样定义订单过滤器:
$scope.todoOrderFilter = function (todo) {
return todo.value1 * todo.value2;
};
在我尝试使每一行都可编辑之前,这到目前为止效果很好。为此,我添加了一个带有输入元素的附加 <div>
来编辑每个 <li>
中的值,还添加了 ng-hide="todo.editing"
和 ng-show="todo.editing"
以便能够将 on/off 编辑模式只需设置 todo.editing=true
或 false
;
完整的 HTML 看起来像这样:
<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>
编辑按钮处理程序:
$scope.editTodo = function(todo) {
todo.editing = true;
};
这有点管用,但是当我编辑 value1 或 value2 的输入字段时,我的排序功能会自动触发,这会导致 <li>
元素上下跳动,这非常糟糕。
所以我基本上想要的是我的自动排序过滤器在 todo.editing=true
.
到目前为止,我在 SO 上发现了这些类似的问题,但它们并没有真正帮助:
- Disabling orderBy in AngularJS while editing the list(不明白如何将那里的答案应用到我的代码中)
- (无人回答)
问题: 如何防止 Angular 在 todo.editing=true
时使用待办事项列表?
我坚信利用 Angular 团队已经为我们编写的代码,并以此为基础进行构建。因此,我认为这是装饰内置 orderBy
过滤器以接受第四个参数 (ignore
) 的完美方案。
我自己还没有对此进行过非常彻底的测试,但它应该可以解决问题;
app.config(function ($provide) {
$provide.decorator('orderByFilter', function ($delegate) {
// Store the last ordered state.
var previousState;
return function (arr, predicate, reverse, ignore) {
// If ignore evaluates to a truthy value, return the previous state.
if (!!ignore) {
return previousState || arr;
}
// Apply the regular orderBy filter.
var order = $delegate.apply(null, arguments);
// Overwrite the previous state with the most recent order state.
previousState = order;
// Return the latest order state.
return order;
}
});
});
用法:
<div ng-repeat="d in data | orderBy:predicate:reverse:ignore">
<!-- in your case -->
<div ng-repeat="todo in selectedList.todos | orderBy:todoOrderFilter:false:todo.editing>
我希望所有这些都有意义(甚至 也行得通™)。
解决方案是编辑对象的副本而不是直接编辑它。然后,当用户完成编辑时,将原始对象替换为副本。