1
votes

I'm binding my ViewModel's isChecked property to a data-whatever attribute. The value of this attribute is changed by jQuery:

$element.data('whatever', "true")

KnockoutJs doesn't notice this change and my ViewModel's property doesn't change. How can I make KnockoutJs notice it?

I tried something like that, but it didn't work:

JavaScript "view layer" script:

$element.data('whatever', "true")
$element.trigger("myCustomEvent")

The view:

<div data-bind="attr: { 'data-whatever': isChecked, event : {myCustomEvent: checkedFunction} }">

checkedFunction is just an empty method in the ViewModel to fit the event binding syntax. It still looks like KnockoutJs is not listening to myCustomEvent.

EDIT

As Fisherman suggested I used $element.attr instead of $element.data, but it still doesn't work:

<html>
<div id="test" data-bind="attr: { 'data-whatever': isChecked }">my div</div>

<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="http://knockoutjs.com/downloads/knockout-3.2.0.js"></script>
<script>
var vm = {
    isChecked : ko.observable("one"),
};

$(function () {
    ko.applyBindings(vm);
    console.log($('#test').attr('data-whatever')); // "one"
    $('#test').attr('data-whatever', 'two');
    console.log($('#test').attr('data-whatever')); // "two"
    console.log(vm.isChecked()); // // "one" again, thouh it should be "two"
});

</script>
</html>

even if I add the event:

<html>
<div id="test" data-bind="attr: { 'data-whatever': isChecked, event :{ myCustomEvent : aFunction }}">my div</div>

<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="http://knockoutjs.com/downloads/knockout-3.2.0.js"></script>
<script>
var vm = {
    isChecked : ko.observable("one"),
    aFunction : function(){ }
};

vm.isChecked.subscribe(function(){
    console.log("hit the event"); // never happens
});

$(function () {
    ko.applyBindings(vm);
    console.log($('#test').attr('data-whatever')); // "one"
    $('#test').attr('data-whatever', 'two');
    $('#test').trigger('myCustomEvent');
    console.log($('#test').attr('data-whatever')); // "two"
    console.log(vm.isChecked()); // "one" again, though should be "two"
});

</script>
</html>
1
Could you edit the question and create a repro? This would make helping you a lot easier. - Jeroen
KO uses jQuery, if it is available, to bind to events. Here is a sample that you could tweak: jsfiddle.net/rniemeyer/Lf53moaa - RP Niemeyer
@Jeroen Added the repro. Please take a look. - Andrzej Gis
@RPNiemeyer Thanks for the sample, but it's not exactly what I need. I'd rather have my view model notified about the change of the attribute bound to the property. Please take a look at the edit. - Andrzej Gis

1 Answers

0
votes

You can't set the data attribute with jQuery's data() functions. Have a look at the documentation: http://api.jquery.com/data/

The data- attributes are pulled in the first time the data property is accessed and then are no longer accessed or mutated (all data values are then stored internally in jQuery)

http://jsfiddle.net/prpL0x3j/

console.log($('#test').data('whatever'));
// one
$('#test').data('whatever', 'two');
console.log($('#test').data('whatever'));
// two

Check out the attribute of the DOM element in the developer bar - it does not change, even though jQuery's data value changed.

Consider using the attr() function: http://api.jquery.com/attr/

$element.attr('data-whatever', "true")