Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何检测项目在剔除可观察数组之间的移动_Javascript_Jquery_Jquery Ui_Knockout.js - Fatal编程技术网

Javascript 如何检测项目在剔除可观察数组之间的移动

Javascript 如何检测项目在剔除可观察数组之间的移动,javascript,jquery,jquery-ui,knockout.js,Javascript,Jquery,Jquery Ui,Knockout.js,我正在使用查询和敲除构建一个web应用程序。 在某一页上,我有几个项目列表。 这些列表是可排序和连接的,所以就JQuery而言,一切正常。我使用Ryan Niemeyer的示例为排序表创建自定义绑定,以更新视图模型的可观察数组 这一切都很好,但我想将更改保存到后端服务器。 使用对可观察阵列的订阅,我可以检测到一个项目从阵列中删除,并添加到阵列中,但这会导致对后端服务器的两个更新调用 如果在其中一个调用期间出现问题,则后端将处于无效状态 如何检测删除一个项目并随后添加相同的项目,以便web应用程序

我正在使用查询和敲除构建一个web应用程序。 在某一页上,我有几个项目列表。 这些列表是可排序和连接的,所以就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
    属性,然后在回调中访问它,这样我就有了一种友好的方法来知道哪个是旧的父数组,哪个是新的父数组:


    Thanx Ryan,使用您的示例,我实现了类似的功能。它需要一些额外的功能,因为在我的应用程序中,添加或删除项目可能有多种原因。顺便说一句,你关于淘汰赛的帖子真的很棒,我经常使用它们!不要以为我会像没有它们时那样多地使用敲除功能。@RogierBessem我最近清理了一下,并在这里为它创建了一个项目:。也许更新的版本对你有用,或者如果你有反馈,请随意分享。谢谢