2012-09-01 3 views
15

habe ich ein Eingabeelement, das mit einem Knockout beobachtbaren gebunden ist:Knockout.JS: Trigger basierend auf Änderungen in einer beobachtbaren

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

Dies aktualisiert die beobachtbare auf jeder keyup. Ich möchte jetzt zusätzliche Ereignisse auslösen, wenn sich der Wert ändert.

Die folgende tut dies im Prinzip:

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

Es ist jedoch etwas klobig zu sein scheint. Es löst auch bei der ersten Instanziierung des Templates aus, wo ich erst danach mit Änderungen umgehen möchte. Gibt es eine offizielle/einfachere Möglichkeit, Ereignisse basierend auf Änderungen an Observablen auszulösen?

Antwort

31

Verwendung abonnieren:

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

Wenn Sie diesen Trigger wiederverwenden möchten Sie betrachten können eine custom binding writting.

+2

+1 für manuelle Abonnements (http://knockoutjs.com/documentation/observables.html#explicitely_subscribing_to_observables) –

+0

Eine benutzerdefinierte Bindung scheint wie Overkill für eine einzelne Eingabe IMHO. Ein Abonnement klingt für mich nach einer besseren Wahl. –

+0

Genau das, was ich gesucht habe. Vielen Dank! - Bezüglich der benutzerdefinierten Bindungen: Gibt es eine Möglichkeit, eine generalisierte Bindung für Felder zu haben, in denen Änderungen andere Ereignisse auslösen sollen, und diese Funktion innerhalb der Bindung im HTML auszuführen? – gzost

3

Wenn Sie in Ihrer verbindlichen dann verwenden allBindings.get(nameOfOtherBinding) und stellen Sie den nameOfOtherBinding Parameter zusätzliche Informationen zu erhalten versuchen, in diesem Element auf den Namen der Bindung zu beziehen, die auf eine Funktion zeigen wird. Setzen Sie das Funktionsliteral entweder in den HTML-Code oder stellen Sie sicher, dass Sie diese Funktion im Gültigkeitsbereich der Handlerdefinition finden (wie global an das Objekt window angehängt).

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

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

Der JavaScript, das die Prozedur (entweder in init oder Update) aufgebaut würde:

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); 

Der HTML-Code, den Handler benutzen würde (Bekanntmachung wie die Elemente mit der "Spaß" -Bindung nicht funktionieren:

<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> 

Sie können auch einfach die init der Bindung verwenden, um Standard-DOM-Event-Handler einzurichten und diese Funktionen nur explizit mit jQuery aufzurufen. Vielen Dank. Schönen Tag.