First: I am new to knockout js, and trying to wrap my head around the knockout/mvvm way of thinking, so please forgive me if my question turns out to be trivial.
What I have is a the following case: I have a knockout viewmodel containing an observableArray of selected ticket objects. This array represents a user-defined selection/subset of a bigger set of tickets. The whole set of tickets are listed in a jqgrid table, and each row has a checkbox which is supposed to be telling whether each ticket is selected or not. This means that the value of the checkbox needs to be updated whenever the "selectedTickets" array changes. In addition to this I also want the user to be able to click each checkbox in order to add/remove a ticket from the selection. Would seem like a fairly acceptable piece of functionality, right?
I do however have trouble seeing how I could use the knockout "checked" binding in order to achieve this. My first idea was to use a puted/dependent observable on the viewmodel object called "isSelected" which would reflect changes in the selectedTickets array and return true or false based on whether a ticket is in the selectedTickets array or not. The first problem here is that I then need to pass a parameter to the puted observable saying which ticket ID it's supposed to look up, and from what I can see that only works on a writable puted observable. Getting the state for the checkbox does however not seem like a write operation, so something already started to smell. Next issue is that the binding needed to be twoway, as I wanted the user to be able to change the state of each checkbox and having the selectedTickets array being updated accordingly. This is a different operation, as it would actually remove/add tickets to the selectedTickets array. Which would again trigger the puted observable trying to set the state of the checkbox. Seems like these two use cases may end up like an infinite loop if I try to do it this way. I haven't found a good way of bining these two use cases by just using the checked binding for the checkboxes.
I could of course do the event handling on the checkboxes manually, by hooking up listeners to the changed event on the checkboxes and to the selectedTickets array in the knockout viewmodel, but I was hoping this was possible to more automated with knockout bindings.
Hope there are some knockout masters out there who can guide me onto a good path, as I feel I've steered off-track with this one.
First: I am new to knockout js, and trying to wrap my head around the knockout/mvvm way of thinking, so please forgive me if my question turns out to be trivial.
What I have is a the following case: I have a knockout viewmodel containing an observableArray of selected ticket objects. This array represents a user-defined selection/subset of a bigger set of tickets. The whole set of tickets are listed in a jqgrid table, and each row has a checkbox which is supposed to be telling whether each ticket is selected or not. This means that the value of the checkbox needs to be updated whenever the "selectedTickets" array changes. In addition to this I also want the user to be able to click each checkbox in order to add/remove a ticket from the selection. Would seem like a fairly acceptable piece of functionality, right?
I do however have trouble seeing how I could use the knockout "checked" binding in order to achieve this. My first idea was to use a puted/dependent observable on the viewmodel object called "isSelected" which would reflect changes in the selectedTickets array and return true or false based on whether a ticket is in the selectedTickets array or not. The first problem here is that I then need to pass a parameter to the puted observable saying which ticket ID it's supposed to look up, and from what I can see that only works on a writable puted observable. Getting the state for the checkbox does however not seem like a write operation, so something already started to smell. Next issue is that the binding needed to be twoway, as I wanted the user to be able to change the state of each checkbox and having the selectedTickets array being updated accordingly. This is a different operation, as it would actually remove/add tickets to the selectedTickets array. Which would again trigger the puted observable trying to set the state of the checkbox. Seems like these two use cases may end up like an infinite loop if I try to do it this way. I haven't found a good way of bining these two use cases by just using the checked binding for the checkboxes.
I could of course do the event handling on the checkboxes manually, by hooking up listeners to the changed event on the checkboxes and to the selectedTickets array in the knockout viewmodel, but I was hoping this was possible to more automated with knockout bindings.
Hope there are some knockout masters out there who can guide me onto a good path, as I feel I've steered off-track with this one.
Share Improve this question edited Jun 13, 2012 at 8:42 Knut Marius asked Jun 13, 2012 at 7:53 Knut MariusKnut Marius 1,6281 gold badge21 silver badges40 bronze badges 2- 6 People dislike text-walls, perhaps you can be more explicit with describing your problem? – Christoph Commented Jun 13, 2012 at 8:45
- 2 I think you mean succinct. He is already being pretty explicit! :) – Umar Farooq Khawaja Commented Sep 25, 2013 at 10:01
1 Answer
Reset to default 6When using knockout.js, you need to stop doing things by halves - if you have a list of items, the data belongs in the viewmodel (not only the select items), and only the appearance is defined by the view.
Thus, I'd remend an observable array items
of type Item
, which has a property isSelected
- the selected items can then be made accessible via a puted observable:
var Item = function(name) {
this.name = ko.observable(name);
this.isSelected = ko.observable(false);
};
var ViewModel = function() {
var self = this;
self.items = ko.observableArray([
new Item('Foo'), new Item('Bar'), new Item('Foo Bar')
]);
self.selectedItems = ko.puted(function() {
return ko.utils.arrayFilter(self.items(), function(item) {
return item.isSelected();
});
});
};
http://jsfiddle/htZfX/