Kristian Nissen
Kristian Nissen

Reputation: 1184

KnockoutJS: Remove array of items from an array

I have a problem with knockoutJS i can't figure out

I have two observableArrays; One containing all available items and one containing all selected items.

How can i return a new array, that contains all the available items ( with all the selected items removed from it)?

Upvotes: 5

Views: 1082

Answers (4)

antishok
antishok

Reputation: 2910

I'd use .filter or ko.utils.arrayFilter, and .indexOf or equivalent:

this.remainingOptions = ko.computed(function(){
    return this.availableOptions().filter(function(option) {
        return this.selectedOptions().indexOf( option ) === -1;
    }.bind(this));
},this);

Fiddle: http://jsfiddle.net/p3RMD/1/

Edit: Also see the Knockout Projections plugin if you want more efficient .map and .filter methods on observableArrays

Upvotes: 3

Kristian Nissen
Kristian Nissen

Reputation: 1184

EDIT:

Since my specific problem, was observableArrays containing objects ( which i failed to state in my question ). The answers provided did not fix my problem, although, it did answer the question nicely, which is why i am not changing answer.

for anyone interested in how i solved the problem, here is the code:

    var self = this;
    self.users = ko.observableArray([]);
    self.roles = ko.observableArray([]);
    self.selectedUser = ko.observable();

    self.remainingOptions = ko.computed(function () {
        return (self.roles()).filter(function (option) {
            var current = option.Name();
            var keep = true;
            if (self.selectedUser() !== undefined) {
                ko.utils.arrayFirst(self.selectedUser().Roles(), function (item) {

                    if (keep) {
                        keep = (current !== item.Name());
                    }
                    return (current === item.Name());
                });
            }
            return keep;
        }); //end  filter
    }); //end remaininOptions

the Role object is just an object with a Name property.

Upvotes: 1

Nathan Jones
Nathan Jones

Reputation: 960

If you want to return a new array, without modifying the original array, your best bet is to use a computed observable.

var ViewModel = function(){
    this.available = ko.observableArray([1,2,3,4,5]);
    this.selected = ko.observableArray([1,3,5]);

    this.remaining = ko.computed(function(){
        var remaining = ko.observableArray();
        remaining(ko.toJS(this.availableOptions))
        remaining.removeAll(this.selectedOptions());
        return remaining();
    }, this);
}

Here's a link to a working example:

http://jsfiddle.net/nathanjones/p3RMD/

Edit: fixed sample code.

Upvotes: 1

pax162
pax162

Reputation: 4735

The standard removeAll method should handle this. From documentation:

myObservableArray.removeAll(['Chad', 132, undefined]) removes all values that equal 'Chad', 123, or undefined and returns them as an array

Do you need to extract the available items without altering the original, all available items array?

Upvotes: 2

Related Questions