Justin
Justin

Reputation: 657

knockout checkbox binding selected value

I am learning knockout and was trying to build a page that will build a list of selectable users. JSFiddle: http://jsfiddle.net/Just/XtzJk/3/ (I am unable to get the data assignment right).

The data assignment is working in my page as I make a call to Controller, like below and it binds to the controls as expected

$.getJSON("/Wizard/GetUsers",function(allData){
        var mappedUsers = $.map(allData.AllUsers, function(item){return new User(item)});
        self.AllUsers(mappedUsers);
        if(allData.SelectedUsers != null){
        var mappedSelectedUsers = $.map(allData.SelectedUsers, function(item){return new User(item)});
        self.SelectedUsers(mappedSelectedUsers);}
    });

Problems:

a.) What's wrong with the JSFiddle I wrote? Got it working.

b.) In my code I am able to get the function for selected checkbox invoked but I am unable to get the value stored in the "User" parameter that I receive in the function. In Chrome JS console I can see the user object has the right value stored, I just am unable to retrieve it. Got this by doing ko.toJS().

Thanks.

EDIT: Ok, I got my JSFiddle working, I had to select Knockout.js in the framework. The updated fiddle: http://jsfiddle.net/Just/XtzJk/5/

Also, for getting the selected checkboxe's value I did

ko.toJS(user).userName

But I think I'll take the approach of selecting values from a list and then on click move them to another "Selected" list and remove the values from the previous ones. Got this idea from this post: KnockoutJS: How to add one observableArray to another?

Upvotes: 1

Views: 10287

Answers (1)

jimmym715
jimmym715

Reputation: 1502

OK, I think I've got the solution you need...

I started by setting up an observable array of selectedUserNames, and I applied this to the <li> elements like this:

<input type="checkbox" 
       name="checkedUser" 
       data-bind="value: userName, checked:$root.selectedUserNames" />

[Note: it's important to declare the value before declaring the checked binding, which threw me for a bit… ya learn something new every day!]

Why bind an array of userName values to the checked binding? Well, when an array is passed to the checked binding, KO will compare the value of each checkbox to the values in the checked array and check any checkbox where its value is in that array. (Probably explained better in the KO documentation)

Then, while I left the observableArray for SelectedUsers, I set up a manual subscription to populate it, like so:

self.selectedUserNames.subscribe(function(newValue) {
    var newSelectedUserNames = newValue;
    var newSelectedUsers = [];
    ko.utils.arrayForEach(newSelectedUserNames, function(userName) {
        var selectedUser = ko.utils.arrayFirst(self.AllUsers(), function(user) {
            return (user.userName() === userName);
        });
        newSelectedUsers.push(selectedUser);
    });
    self.SelectedUsers(newSelectedUsers);
});

[I had originally tried to set up a dependent observable (ko.computed) for selectedUserNames with functions for both read and write, but the checkbox wasn't having it.]

This subscription function examines the new selectedUserNames array, looks up the user from AllUsers whose userName matches a value in that selectedUserNames array, and pushes matching User objects to the SelectedUsers array… well, actually it pushes each matching User to a temp array and then that temp array is assigned to SelectedUsers, but the goal is met. The SelectedUsers array will now always contain what we want it to contain.

Oh, I almost forgot… here's the fiddle I created, so you've got the full solution: http://jsfiddle.net/jimmym715/G2hxP/

Hope this helps, but let me know if you have any questions

Upvotes: 8

Related Questions