8

Dies scheint ein gängiger Ansatz zum Bereinigen/Validieren/Formatieren von Daten mit Knockout beim Binden an ein Eingabefeld ist, erstellt es eine wiederverwendbare benutzerdefinierte Bindung, die eine berechnete Observable verwendet. Es erweitert im Grunde die Standardwertbindung, um einen Interzeptor einzuschließen, der Eingaben vor dem Schreiben/Lesen formatiert/bereinigt/validiert.Knockout.js Erweitern Wert Bindung mit Interceptor

ko.bindingHandlers.amountValue = { 
    init: function (element, valueAccessor, allBindingsAccessor) { 
    var underlyingObservable = valueAccessor(); 

    var interceptor = ko.computed({ 
     read: function() { 
     // this function does get called, but it's return value is not used as the value of the textbox. 
     // the raw value from the underlyingObservable is still used, no dollar sign added. It seems like 
     // this read function is completely useless, and isn't used at all 
     return "$" + underlyingObservable(); 
     }, 

     write: function (newValue) { 
     var current = underlyingObservable(), 
      valueToWrite = Math.round(parseFloat(newValue.replace("$", "")) * 100)/100; 

     if (valueToWrite !== current) { 
      // for some reason, if a user enters 20.00000 for example, the value written to the observable 
      // is 20, but the original value they entered (20.00000) is still shown in the text box. 
      underlyingObservable(valueToWrite); 
     } else { 
      if (newValue !== current.toString()) 
      underlyingObservable.valueHasMutated(); 
     } 
     } 
    }); 

    ko.bindingHandlers.value.init(element, function() { return interceptor }, allBindingsAccessor); 
    }, 

    update: ko.bindingHandlers.value.update 
}; 

jsFiddle Beispiel: http://jsfiddle.net/6wxb5/1/

Bin ich etwas fehlt? Ich habe diese Methode überall gesehen, aber es scheint nicht vollständig zu funktionieren. Die Lesefunktion scheint völlig nutzlos, da sie überhaupt nicht verwendet wird. In der Schreibfunktion ändert die Eingabe von "23.0000" den geschriebenen Wert in 23, aber die Textboxwerte werden nicht aktualisiert.

Antwort

13

Das Problem kommt aus dem update Teil Ihrer benutzerdefinierten Bindung. Dieser Teil aktualisiert das Feld basierend auf dem ursprünglichen Modellwert. Also, der Event-Handler im Anhang init wird den neuen Wert durch Ihre Writeable berechnet, aber die Aktualisierung des Feldes geschieht tatsächlich in der update.

Eine Möglichkeit ist, den Wert Bindung von Ihrer init Funktion und lassen Sie die update Funktion wie anwenden:

ko.bindingHandlers.amountValue = { 
    init: function (element, valueAccessor, allBindingsAccessor) { 
    var underlyingObservable = valueAccessor(); 

    var interceptor = ko.computed({ 
     read: function() { 
     // this function does get called, but it's return value is not used as the value of the textbox. 
     // the raw value from the underlyingObservable, or the actual value the user entered is used instead, no 
     // dollar sign added. It seems like this read function is completely useless, and isn't used at all 
     return "$" + underlyingObservable(); 
     }, 

     write: function (newValue) { 
     var current = underlyingObservable(), 
      valueToWrite = Math.round(parseFloat(newValue.replace("$", "")) * 100)/100; 

     if (valueToWrite !== current) { 
      // for some reason, if a user enters 20.00000 for example, the value written to the observable 
      // is 20, but the original value they entered (20.00000) is still shown in the text box. 
      underlyingObservable(valueToWrite); 
     } else { 
      if (newValue !== current.toString()) 
      underlyingObservable.valueHasMutated(); 
     } 
     } 
    }); 

     ko.applyBindingsToNode(element, { value: interceptor }); 
    } 
}; 

Aktualisiert Geige: http://jsfiddle.net/rniemeyer/Sr8Ev/

+0

Danke, das war frustrierend;) –

+0

aktualisiert Geige. http://jsfiddle.net/Sr8Ev/19/ –