如何检测项目在可观察阵列之间的移动
How to detect moving of an item between knockout observable arrays
我正在使用查询和敲除构建一个web abb。在某个页面上,我有几个项目列表。这些列表是可排序和连接的,所以就JQuery而言,一切都正常。我用Ryan Niemeyer的例子为可排序列表创建了一个自定义绑定,以更新我的视图模型的可观察数组。
这一切都很好,但我想将更改保存到后端服务器。使用对可观察阵列的订阅,我可以检测到一个项目被从阵列中删除并添加到阵列中,但这会导致对后端服务器的两次更新调用。
如果在其中一个调用过程中出现问题,那么后端将处于无效状态。
如何检测项目的删除和随后添加同一项目,以便web应用程序可以对后端服务器进行一次性调用?
我认为处理这一问题的一个好方法是向sortableList绑定添加一个回调选项,该选项将项、原始父项和新父项作为参数传递。
以下是我在KO 2.0中使用的回调绑定:
//connect items with observableArrays
ko.bindingHandlers.sortableList = {
init: function(element, valueAccessor, allBindingsAccessor, data, context) {
var options = ko.utils.unwrapObservable(valueAccessor());
//attach the appropriate class to our element
if (ko.bindingHandlers.sortableList.autoAddClass) {
ko.utils.toggleDomNodeCssClass(element, ko.bindingHandlers.sortableList.defaultClass, true);
}
$(element).data("sortList", options.list || valueAccessor()); //attach meta-data
$(element).sortable({
update: function(event, ui) {
var item = ui.item.data("sortItem");
if (item) {
//identify parents
var originalParent = ui.item.data("parentList");
var newParent = ui.item.parent().data("sortList");
//figure out its new position
var position = ko.utils.arrayIndexOf(ui.item.parent().children(), ui.item[0]);
if (position >= 0) {
originalParent.remove(item);
newParent.splice(position, 0, item);
}
ui.item.remove();
if (options.afterDrop) {
options.afterDrop.call(this, item, newParent, originalParent);
}
}
},
connectWith: '.' + ko.bindingHandlers.sortableList.defaultClass
});
return ko.bindingHandlers.template.init.apply(this, arguments);
},
update: function(element, valueAccessor, allBindingsAccessor, data, context) {
var options = ko.utils.unwrapObservable(valueAccessor()),
newOptions = {};
//build our options to pass to the template engine
if (options.list) {
newOptions.foreach = options.list;
newOptions.name = options.tmpl;
newOptions.includeDestroyed = options.includeDestroyed;
newOptions.afterAdd = options.afterAdd;
newOptions.beforeRemove = options.beforeRemove;
} else {
newOptions.foreach = valueAccessor();
}
//use an afterRender function to add meta-data
if (options.afterRender) {
//wrap the existing function, if it was passed
newOptions.afterRender = function(element, data) {
ko.bindingHandlers.sortableList.afterRender.call(data, element, data);
options.afterRender.call(data, element, data);
}
} else {
newOptions.afterRender = ko.bindingHandlers.sortableList.afterRender;
}
//call the actual template binding
ko.bindingHandlers.template.update(element, function() { return newOptions; }, allBindingsAccessor, data, context);
},
afterRender: function(elements, data) {
ko.utils.arrayForEach(elements, function(element) {
if (element.nodeType === 1) {
$(element).data("sortItem", data);
$(element).data("parentList", $(element).parent().data("sortList"));
}
});
},
defaultClass: 'container',
autoAddClass: true
};
然后,您可以指定绑定,如:
<ul data-bind="sortableList: { tmpl: 'myItems', list: myObservableArray, afterDrop: myCallback }"></ul>
现在,您可以添加自己的回调,以告诉服务器项目已被移动。observableArray是函数(它是对象),所以您实际上可以为它们分配属性。下面是一个示例,我为每个可观察数组分配了一个id
属性,然后在回调中访问它,这样我就可以用一种友好的方式来知道哪个是旧的父数组,哪个是新的父数组:
http://jsfiddle.net/rniemeyer/QZscP/
相关文章:
- knockoutjs可观察数组
- 多次发射多个可观察器的问题
- 未激发路由的控制器属性上的观察者
- 无法在关闭弹出窗口时传递可观察的数据
- 使用正则表达式捕获“”并分割成阵列
- AngularJS卡片转盘:将卡片返回到阵列的末尾
- firefox插件:退出不工作的应用程序观察器
- 从不同的对象创建阵列
- 如何观察控制器/组件内阵列的变化
- 敲除和可观察阵列不匹配
- 阵列突变而不触发特定的观察者
- 微风导航阵列成员是淘汰赛中的可依赖观察对象
- 如何在敲除中对可观察阵列应用多个滤波器
- 如何正确放置$scope$观察二维阵列
- 依赖可观察器中的大型阵列-级联
- 如何检测项目在可观察阵列之间的移动
- 聚合物1.0阵列观察者的结合变化
- 聚合物-如何将观察者连接到阵列
- 聚合物:用复杂观察者观察阵列突变
- 聚合物1.0观察阵列