Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout.JS: Triggers based on changes in an observable

I have an input element which is bound to a knockout observable:

<input type="text" data-bind="value: myText, valueUpdate: 'keyup'" />

This updates the observable on each keyup. I now want to trigger additional events when the value changes.

The following does this in principle:

this.myTextTrigger = ko.computed( function () {
    console.log( this.myText() );
}, this );

However, it seems somewhat clunky. It also triggers on the initial instantiation of the template, where I only want to handle changes after that. Is there an official/easier way to trigger events based on changes to observables?

like image 877
gzost Avatar asked Sep 01 '12 17:09

gzost


People also ask

How do you get the Knockout value from observable?

To read the observable's current value, just call the observable with no parameters. In this example, myViewModel. personName() will return 'Bob' , and myViewModel. personAge() will return 123 .

What is the use of observable in knockout JS?

Knockout. js defines an important role when we want to detect and respond to changes on one object, we uses the observable. An observable is useful in various scenarios where we are displaying or editing multiple values and require repeated sections of the UI to appear and disappear as items are inserted and deleted.

Is knockout js still used?

It is still usable, I use it all the time. It's a great framework to use on legacy applications where you don't want your JS framework messing with anything, like angular hooking into anchor urls etc…

What is applyBindings in Knockout?

A binding context is an object that holds data that you can reference from your bindings. While applying bindings, Knockout automatically creates and manages a hierarchy of binding contexts. The root level of the hierarchy refers to the viewModel parameter you supplied to ko. applyBindings(viewModel) .


2 Answers

Use subscribe:

this.myText.subscribe(function (newText) {
   console.log(newText);
});

If you want to reuse this trigger you can consider writting a custom binding.

like image 166
meze Avatar answered Oct 05 '22 11:10

meze


If you are trying to get extra information in your binding then use allBindings.get(nameOfOtherBinding) and set the nameOfOtherBinding parameter to refer to the name of the binding in that element which is pointing to a function. Either put the function literal in the HTML or make sure you can find that function in scope of the handlers definition (like globally attached to the window object).

http://knockoutjs.com/documentation/custom-bindings.html

JS Fiddle Example - http://jsfiddle.net/pqb4xubg/

The javascript that would set up the handler(either in init or update):

ko.bindingHandlers.generic = {
    init: function(element, valueAccessor, allBindings){
        var val = 'nothing';
        // set your other bindings to get pulled in
        var func = allBindings.get('func');
        // normal check if the binding is actually a function
        if(typeof func === 'function'){
            // use the retrieved function
            val = func(valueAccessor());
        }
        element.innerText = val;
    }
};
var model = {a:'4', b:5};
ko.applyBindings(model);

The html that would use the handler (notice how the elements with the "fun" binding do not work):

<div data-bind="generic: a, func: function( val ){ return val + 2; }"></div>
<div data-bind="generic: a, fun: function( val ){ return val + 2; }"></div>
<div data-bind="text: a"></div>
<div data-bind="generic: b, func: function( val ){ return val + 2; }"></div>
<div data-bind="generic: b, fun: function( val ){ return val + 2; }"></div>
<div data-bind="text: b"></div>

You can also just use the init of the bind to setup standard DOM event handlers and just explicitly call those functions using something like jQuery. Thank you. Good day.

like image 3
Yemi Bedu Avatar answered Oct 05 '22 11:10

Yemi Bedu