Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

KnockoutJS property doesn't update when changing value with Jquery

I have a serie of checkboxes and I want to gather the selected one. The checkboxes are in div's and when the div is clicked the checkbox should get checked as well:

var oCheckBox = $($(this).find('.chkSocialMediaItem').get(0));
oCheckBox.attr('checked', !$(oCheckBox).attr('checked'));

This works just fine but KnockoutJS doesn't pick up the change and so doesn't update my counter on the selected items.

I read somewhere you need to trigger the change event. But when I listen to the change event on the checkbox it does actually get triggered.

Any help would be appreciated, Thanks !

Update:

I have found a 'knockout' solution. In my div I did a data-bind off the 'click' and changed the checked value in that function:

<script type="text/html" id="Template">
    <div class="item" data-bind="click: DivClicked">
       <input type="checkbox" data-bind="checked: IsASelectedItem" class="chkSocialMediaItem"/>
    </div>
</script>


function SocialMediaSearchItem() {          
            this.IsASelectedItem = ko.observable();
            this.DivClicked = function () {
                this.IsASelectedItem(!this.IsASelectedItem());
            };
}

Is this the only solution? I would really like 2 see a Jquery solution as well.

like image 344
Kevin Cloet Avatar asked Oct 14 '11 12:10

Kevin Cloet


People also ask

Does knockout use jQuery?

Knockout out provides a sophisticated way to use jQuery methods with your binding.

What is knockout mapping?

Knockout is designed to allow you to use arbitrary JavaScript objects as view models. As long as some of your view model's properties are observables, you can use KO to bind to them to your UI, and the UI will be updated automatically whenever the observable properties change.

What is $data in knockout JS?

In the root context, $data and $root are equivalent. Inside a nested binding context, this parameter will be set to the current data item (e.g., inside a with: person binding, $data will be set to person ). $ data is useful when you want to reference the viewmodel itself, rather than a property on the viewmodel.

What is applyBindings in knockout?

To apply bindings for the whole HTML document, it can be done using the Knockout function applyBindings() with passing the view model as the first and the only parameter: ko. applyBindings(viewModel); To apply Knockout for a part of the HTML document, pass the DOM element as a second parameter: ko.


2 Answers

I ran into the same issue... Although I did find a solution that worked for me that differed from the one posted by @RP Niemeyer, so I figured I would post it.

Knockout Version: 1.2.1 -- (knockout-1.2.1.js)

To uncheck the checkbox bound by Knockout I used the following

$('YourCheckBoxHere').removeAttr('checked');
$('YourCheckBoxHere').triggerHandler('click');

to check the checkbox bound by Knockout I used the following

$('YourCheckBoxHere').attr('checked', 'true');
$('YourCheckBoxHere').triggerHandler('click');

Hopefully if the other solution didnt work, perhaps this will =) ... wasted about 3 hours on this issue.

like image 116
afreeland Avatar answered Sep 18 '22 09:09

afreeland


The checked binding only listens to the click event. Manually triggering the click event ends up getting the box out-of-sync based on when the actual checked value is set.

The preferred way to set the value is to update your view model value, as you have done in your second example above.

However, if you are using 1.3beta, then there is an easy way to connect an element with its corresponding data using the ko.dataFor API. It would look something like:

  var oCheckBox = $('.chkSocialMediaItem'),
      data = ko.dataFor(oCheckBox[0]);
      data.selectedItem(!data.selectedItem());
like image 43
RP Niemeyer Avatar answered Sep 17 '22 09:09

RP Niemeyer