How do I swap two items in an observableArray?

后端 未结 4 1853
轮回少年
轮回少年 2020-12-03 05:05

I have a button that moves an item one position left in an observableArray. I am doing it the following way. However, the drawback is that categories()[index] gets removed f

相关标签:
4条回答
  • 2020-12-03 05:34

    I know this answer comes a bit late, but I thought it might be useful to others who want a more general swap solution. You can add a swap function to your observableArrays like so:

    ko.observableArray.fn.swap = function(index1, index2) {
        this.valueWillMutate();
    
        var temp = this()[index1];
        this()[index1] = this()[index2];
        this()[index2] = temp;
    
        this.valueHasMutated();
    }
    

    You can then use this function to swap two elements in an array given their indices:

    myArray.swap(index1, index2);
    

    For a moveUp function, you could then do something like this:

    moveUp: function(category) {
        var i = categories.indexOf(category);
        if (i > 0) {
            categories.swap(i, i+1);
        }
    }
    
    0 讨论(0)
  • 2020-12-03 05:40

    I had a similar problem as I wanted jQuery drag & drop on my items. My solution became to use knockoutjs templates to bind the beforeRemove and afterAdd events to the model. The Person Class/function is also a simple knockout view model.

    In the below example I use .draggable(), but you could easily use validation. Add your own code for manipulating the observableArray and you should be good to go.

    HTML:

    <div data-bind="template: {foreach:attendeesToShow, beforeRemove:hideAttendee, afterAdd:showAttendee}">
        <div class="person">
            <img src="person.jpg" alt="" />
            <div  data-bind="text: firstName" ></div>
            <div class="deleteimg" data-bind="click:$parent.removeAttendee" title="Remove"></div>
        </div>
    </div>
    

    ViewModel:

    var ViewModel = function () {
        var self = this;
        var at = [new Person('First', 'Person', 'first@example.com'),
                        Person('Second', 'Person', 'second@example.com')
                    ];
        self.attendees = ko.observableArray(at);
    
        self.removeAttendee = function (attendee) {
            self.attendees.remove(attendee);
        };
    
        this.showAttendee = function (elem) {
            if (elem.nodeType === 1) {
        $(elem).hide().show("slow").draggable();//Add jQuery functionality 
            }
        };
        this.hideAttendee = function (elem) {
            if (elem.nodeType === 1) {
                $(elem).hide(function () {
                    $(elem).remove();
                });
            }
        };
    };
    
    ko.applyBindings(new ViewModel());
    
    0 讨论(0)
  • 2020-12-03 05:44

    thanks to Michael Best for his version of moveup

    my version of moveDown

    moveDown: function(category) {
        var array = categories();
        var i = categories.indexOf(category);
        if (i < arr.length) {
            categories.splice(i, 2, array[i + 1], array[i]);
        }
    }
    
    0 讨论(0)
  • 2020-12-03 05:56

    Here's my version of moveUp that does the swap in one step:

    moveUp: function(category) {
        var i = categories.indexOf(category);
        if (i >= 1) {
            var array = categories();
            categories.splice(i-1, 2, array[i], array[i-1]);
        }
    }
    

    That still doesn't solve the problem, though, because Knockout will still see the swap as a delete and add action. There's an open issue for Knockout to support moving items, though. Update: As of version 2.2.0, Knockout does recognize moved items and the foreach binding won't re-render them.

    0 讨论(0)
提交回复
热议问题