Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding a list of objects to a list of checkboxes

Tags:

knockout.js

I have a list of objects, each with a few fields, like this:

function Person(id,name,age) {
    this.id = id;
    this.name = name;
    this.age = age;
}

var listOfPeople = [
    new Person(1, 'Fred', 25),
    new Person(2, 'Joe', 60),
    new Person(3, 'Sally', 43)
];

var viewModel = {
    this.people = ko.observableArray(listOfPeople);
    this.selectedPeople = ko.observableArray([]);
}

I would like to build a list of checkboxes, one for each person, something along these lines:

<ul data-bind="foreach: people">
    <li>
        <input type="checkbox" data-bind="value: id, checked: ?">
        <span data-bind="name"></span>
    </li>
</ul>

My confusion is that in the checkbox data-bind attribute, I would like to refer to both the object being selected (that is, the person or the person's id), as well as to the list of all selected people. How do I refer to that in the scope of the foreach binding?

I guess a corollary is: how do I refer to the object being bound? Here "this" seemed to be bound to the window, not to the object.

The example of the "checked binding on the knockoutjs site" deals with primitives and uses a named template. I am confused about how to do this with objects and with anonymous templates.

like image 342
Gene Golovchinsky Avatar asked Dec 23 '11 08:12

Gene Golovchinsky


1 Answers

You can do something like:

<ul data-bind="foreach: people">
    <li>
        <input type="checkbox" 
               data-bind="checkedValue: id, checked: $parent.selectedPeople">
    </li>
</ul>

With this kind of ViewModel:

var viewModel = {
    people: ko.observableArray(listOfPeople),
    selectedPeople: ko.observableArray()
};

The value attribute controls what the checked binding adds/removes from an array when it is bound against an array. You could also write a dependentObservable that populates the array with the actual objects, if necessary.

Live Example:

function Person(id,name,age) {
    this.id = id;
    this.name = name;
    this.age = age;
}

var listOfPeople = [
    new Person(1, 'Fred', 25),
    new Person(2, 'Joe', 60),
    new Person(3, 'Sally', 43)
];

var viewModel = {
    people: ko.observableArray(listOfPeople),
    selectedPeople: ko.observableArray([1])
};

    
ko.applyBindings(viewModel);
<ul data-bind="foreach: people">
    <li>
        <input type="checkbox" value="" data-bind="checkedValue: id, checked: $parent.selectedPeople"><span data-bind="text: name"></span>
    </li>
</ul>

<hr/>

<div data-bind="text: ko.toJSON($root)"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
like image 149
RP Niemeyer Avatar answered Nov 05 '22 04:11

RP Niemeyer