Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing objects from observableArray

Tags:

knockout.js

I'm running into a problem with removing objects in an observable array. I have a removeItemFromQueue function that should remove the selected object from a queue.

This example shows that if you add a bunch the items to the queue and then remove one, it removes all of them:

<h3>Items:</h3>

<ul data-bind="template: {name:'itemsTemplate', foreach: items}"></ul>

<h3>Queue:</h3>

<ul data-bind="template: {name:'queueTemplate', foreach: queue}"></ul>

<script id="itemsTemplate" type="text/x-jquery-tmpl">
    <li>
        <a href="#">${$data.title}</a> by <a href="#">${$data.description}</a>
        <button data-bind="click: function() {viewModel.removeItemFromPage($data);}">Remove From Page</button>
        <button data-bind="click: function() {viewModel.addItemToQueue($data);}">Add To Queue</button>
    </li>
</script>

<script id="queueTemplate" type="text/x-jquery-tmpl">
    <li>
        <a href="#">${$data.title}</a> by <a href="#">${$data.description}</a>
        <button data-bind="click: function() {viewModel.removeItemFromQueue($data);}">Remove From Queue</button>
    </li>
</script>

This is the Javascript:

function Item(title, description) {
    this.title = ko.observable(title);
    this.description = ko.observable(description);
}

var viewModel = {
    items: ko.observableArray([
        new Item("one", "one description")
    ]),
    queue: ko.observableArray([]),
    addItemToQueue: function (item) {
        this.queue.push(item);
    },
    removeItemFromPage: function (item) {
        this.items.remove(item);
    },
    removeItemFromQueue: function (item) {
        this.queue.remove(item);
    }
};

ko.applyBindings(viewModel);

I found this workaround using ko.toJS(item) in the addItemToQueue function:

<h3>Items:</h3>

<ul data-bind="template: {name:'itemsTemplate', foreach: items}"></ul>

<h3>Queue:</h3>

<ul data-bind="template: {name:'queueTemplate', foreach: queue}"></ul>

<script id="itemsTemplate" type="text/x-jquery-tmpl">
    <li>
        <a href="#">${$data.title}</a> by <a href="#">${$data.description}</a>
        <button data-bind="click: function() {viewModel.removeItemFromPage($data);}">Remove From Page</button>
        <button data-bind="click: function() {viewModel.addItemToQueue($data);}">Add To Queue</button>
    </li>
</script>

<script id="queueTemplate" type="text/x-jquery-tmpl">
    <li>
        <a href="#">${$data.title}</a> by <a href="#">${$data.description}</a>
        <button data-bind="click: function() {viewModel.removeItemFromQueue($data);}">Remove From Queue</button>
    </li>
</script>

And this Javascript:

function Item(title, description) {
    this.title = ko.observable(title);
    this.description = ko.observable(description);
}

var viewModel = {
    items: ko.observableArray([
        new Item("one", "one description")
    ]),
    queue: ko.observableArray([]),
    addItemToQueue: function (item) {
        this.queue.push(ko.toJS(item));
    },
    removeItemFromPage: function (item) {
        this.items.remove(item);
    },
    removeItemFromQueue: function (item) {
        this.queue.remove(item);
    }
};

ko.applyBindings(viewModel);

Is there an easier approach?

Also, the cart example here looks to be using similar code to my first example, but does not suffer the same issue with removing items. I'm a bit baffled.

like image 918
RustyDev Avatar asked Mar 04 '26 17:03

RustyDev


1 Answers

The problem that you are having is that you are adding the same item multiple times to your queue array.

The remove function of an observableArray will remove all copies of the item that you pass into it.

ko.toJS is one way to get a clean copy of your data. However, you will lose any observables, if you need them.

Otherwise, you might want to do something like:

this.queue.push(new Item(item.title(), item.description()) or write a function that will help you make a copy of the item (pass in an item and return a new item).

like image 57
RP Niemeyer Avatar answered Mar 08 '26 17:03

RP Niemeyer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!