2013-06-11 6 views
17

i viele Tutorials lesen, aber ich weiß nicht, wie dies zu tun, ist dies der Eingangeine Eingabe nur numerischen Typ auf Knockout machen

input(type="text",name="price",id="price"data-bind="text: price,valueUpdate:['afterkeydown','propertychange','input']") 

und das ist mein Ansichtsmodell

price: ko.computed(function() 
{ 
    return parseFloat(this.replace(' ','').replace(/[^0-9\.]+/g,"")) || ''; 
},this) 

aber Ursache Fehler: Das hat keine Methode ersetzen ??? Wie kann ich den Preiswert an die berechnete Funktion übergeben?

+1

Statt 'input type = "text"', was ist, wenn Sie es 'input type = "number" ändern'? Ich denke, dass diese begrenzen, was Sie in sie nur zu numerischen Werten setzen. – jonhopkins

+3

type = "Nummer" hat weniger Kompatibilität mit einigen Browsern – andrescabana86

+1

Jon ist richtig, dass Sie Typ zu Nummer ändern können, aber wenn ich mich richtig erinnere, unterstützen nicht alle Browser diesen Typ. Zum Beispiel glaube ich, alles vor IE10 lassen Sie Text in dort ohne Probleme setzen –

Antwort

37

Ist besser, benutzerdefinierte Bindung http://knockoutjs.com/documentation/custom-bindings.html zu erstellen, die nur zulässige Zeichen [0-9,] als numerische Darstellung akzeptieren.

setzen Sie diese Zeile in Ihre Ansicht

<input id="text" type="text" data-bind="numeric, value: number"> 

diese Zeile in Ihr Modell setzen (denken Sie daran Nummer als beobachtbare Eigenschaft zu binden)

ko.bindingHandlers.numeric = { 
    init: function (element, valueAccessor) { 
     $(element).on("keydown", function (event) { 
      // Allow: backspace, delete, tab, escape, and enter 
      if (event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 13 || 
       // Allow: Ctrl+A 
       (event.keyCode == 65 && event.ctrlKey === true) || 
       // Allow: . , 
       (event.keyCode == 188 || event.keyCode == 190 || event.keyCode == 110) || 
       // Allow: home, end, left, right 
       (event.keyCode >= 35 && event.keyCode <= 39)) { 
       // let it happen, don't do anything 
       return; 
      } 
      else { 
       // Ensure that it is a number and stop the keypress 
       if (event.shiftKey || (event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 105)) { 
        event.preventDefault(); 
       } 
      } 
     }); 
    } 
}; 
+2

Funktioniert das wirklich? Für mich aktualisiert es Observable nicht, wenn es irgendwo auf der Benutzeroberfläche ist? Zum Beispiel haben Sie wie oben und auch einige . Wenn der Benutzer in diesem Fall die Nummer innerhalb der Eingabe bearbeitet, wird die Benutzeroberfläche nach der Bearbeitung nicht aktualisiert. – renathy

+0

Änderungen werden nach dem Ändern des Fokus vom Eingabefeld übernommen. Hier ist ein einfaches Beispiel mit Live Edit (ohne Fokusänderung). http://jsfiddle.net/jakethashi/L7UEm/ –

+0

@renathy Ich verließ die TextInput Bindung, und fügte die numerische als eine zweite Bindung, funktioniert gut – LobsterMan

1

Ein alternativer Ansatz: ich gefunden habe, dass Knockout funktioniert gut in Kombination mit jQuery-validate. Sie müssen nur sicherstellen, dass Sie das Formular validieren, bevor Sie versuchen, den numerischen Wert zu verwenden.

Sagen Sie bitte ein Formular DOM-Element haben, können Sie Validierungsregeln über

$(".yourform").validate({ 
    rules: { 
     year: { 
      digits: true, 
      minlength: 4, 
      maxlength: 4 
     } 
    }, 
    messages: { 
     year: "Please enter four digits (e.g. 2009).", 
    } 
}); 

In Ihrem Viewmodel stellen Sie die Zwei-Wege-Bindung wie üblich, zum Beispiel einrichten über self.year = ko.observable(""). Stellen Sie jetzt sicher, dass Sie $(".yourform").valid() aufrufen, bevor Sie self.year() weiterverarbeiten. In meinem Fall mache ich var year = parseInt(self.year(), 10). Es wird erwartet, dass dies unmittelbar nach der Formvalidierung immer zu einem aussagekräftigen Ergebnis führt.

7

Knockout hat Extender dafür. Check This von knockoutjs.com, das erklärt, wie man beobachtbare Extender benutzt, um Eingabe zu zwingen, numerisch zu sein. Ich fügen Sie den Code aus der Dokumentation hier:

Quellcode: Ansicht

<p><input data-bind="value: myNumberOne" /> (round to whole number)</p> 
<p><input data-bind="value: myNumberTwo" /> (round to two decimals)</p> 

Quellcode: Ansicht Modell

ko.extenders.numeric = function(target, precision) { 
    //create a writable computed observable to intercept writes to our observable 
    var result = ko.pureComputed({ 
     read: target, //always return the original observables value 
     write: function(newValue) { 
      var current = target(), 
       roundingMultiplier = Math.pow(10, precision), 
       newValueAsNum = isNaN(newValue) ? 0 : parseFloat(+newValue), 
       valueToWrite = Math.round(newValueAsNum * roundingMultiplier)/roundingMultiplier; 

      //only write if it changed 
      if (valueToWrite !== current) { 
       target(valueToWrite); 
      } else { 
       //if the rounded value is the same, but a different value was written, force a notification for the current field 
       if (newValue !== current) { 
        target.notifySubscribers(valueToWrite); 
       } 
      } 
     } 
    }).extend({ notify: 'always' }); 

    //initialize with current value to make sure it is rounded appropriately 
    result(target()); 

    //return the new computed observable 
    return result; 
}; 

function AppViewModel(one, two) { 
    this.myNumberOne = ko.observable(one).extend({ numeric: 0 }); 
    this.myNumberTwo = ko.observable(two).extend({ numeric: 2 }); 
} 

ko.applyBindings(new AppViewModel(221.2234, 123.4525)); 
1
<input type="text" id="alpha-validation" data-bind="value: YourDataName, valueUpdate: 'afterkeydown' , event: { 'input': AlphaCheck}" style="text-transform:uppercase"> 

AlphaCheck Funktion erstellen und diese hinzufügen.

$('#alpha-validation').keyup(function() { 
     if (this.value.match(/[^0-9 ]/g)) { 
      this.value = this.value.replace(/[^0-9 ]/g, ''); 
     } 
    }); 

Das wird funktionieren!

-1

Ich weiß, dass diese Frage ein Jahr alt ist, aber lassen Sie mich dies für Feature-Besucher der Seite veröffentlichen.

Check this out:

ko.bindingHandlers.numericnumbers = { 
init: function (element) { 
    $(element).on('keypress', function (number) { 
     number = (number) ? number : window.event; 
     var charcode = (number.which) ? number.which : number.keyCode; 
     if (charcode > 31 && (charcode < 48 || charcode > 75)) 
      number.preventDefault(); 
    }); 
}}; 
0

Erstellen Sie Daten-bind an Ihrem glänzenden neuen Code zeigt:

<input id="price" name="price" type="text" data-bind="numeric"> 

Shiny neue Knockout-Code:

price = ko.observable(); 
price.subscribe(function(newValue) { 
    price = newValue.replace(/[\D\.]/g, ''); 
}); 

Das bedeutet, dass jeder Wenn Sie den Preis aktualisieren, wird die Logik in der Funktion angewendet (in diesem Fall wird alles entfernt, was ist) nicht eine Nummer oder eine Periode), und wenden Sie es direkt auf den Preis an. Sie können auch andere Validierung oder coole Funktionen hier hinzufügen, wie eine Währung sybmol am Start hinzufügen, es auf 2 Dezimalstellen halten, etc ...

0

Mit Hilfe von "Keydown" -Ereignis können wir andere Schlüssel im Text beschränken Box, die numerische Werte enthalten sollte.

$(document).ready(function(){     
     $("selector").on("keydown", function (e) { 
      //numbers, delete, backspace, arrows 
      var validKeyCodes = [8, 9, 37, 38, 39, 40, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57]; 
      if (!($.inArray(e.keyCode, validKeyCodes) >= 0)) 
        e.preventDefault();     
     });   
    }); 
0

Wir können Benutzer auf Eingabebenutzer mehr als zwei Dezimalzahl Ex einschränken. 23.81, 3452.83 Modifizierter Code ist wie folgt. Der Referenzcode stammt aus der Antwort @Martin Surynek.

HTML -

<p> 
    <input data-bind="value: myNumberOne" /> (round to whole number)</p> 
    <p> 
    <input data-bind="num, value: myNumberTwo" /> (round to two decimals)</p> 

Script -

<script> 
    ko.bindingHandlers.num = { 
     init: function (element, valueAccessor) { 
     $(element).on("keypress", function (event) { 
      //debugger 
      console.log(event.keyCode); 
      var $this = $(this); 
      var text = $this.val(); 

      // Stop insert two dots 
      if ($this.val().indexOf('.') != -1 && (event.which == 190 || event.which == 110)) { 
      event.preventDefault(); 
      } 

      // Allow: backspace, delete, tab, escape, and enter 
      if (event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 
      13 || 
      // Allow: Ctrl+A 
      (event.keyCode == 65 && event.ctrlKey === true) || 
      // Allow: . ,event.keyCode == 188 || 
      (event.keyCode == 190 || event.keyCode == 110) || 
      // Allow: home, end, left, right 
      (event.keyCode >= 35 && event.keyCode <= 39)) { 
      // let it happen, don't do anything 
      return; 
      } 

      // Ensure that it is a number and stop the keypress 
      if (event.shiftKey || (event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 
       105)) { 
      event.preventDefault(); 
      } 

      if ((event.which == 46) && (text.indexOf('.') == -1)) { 
      setTimeout(function() { 
       if ($this.val().substring($this.val().indexOf('.')).length > 3) { 
       $this.val($this.val().substring(0, $this.val().indexOf('.') + 3)); 
       } 
      }, 1); 
      } 

      if ((text.indexOf('.') != -1) && 
      (text.substring(text.indexOf('.')).length > 2) && 
      (event.which != 0 && event.which != 8) && 
      ($(this)[0].selectionStart >= text.length - 2)) { 
      event.preventDefault(); 
      }   
      //console.log($(this)[0].selectionStart >= text.length - 2); 
     }); 
     } 
    }; 


    ko.extenders.numeric = function (target, precision) { 
     //create a writable computed observable to intercept writes to our observable 

     var result = ko.pureComputed({ 
     read: target, //always return the original observables value 
     write: function (newValue) { 

      var current = target(), 
      roundingMultiplier = Math.pow(10, precision), 
      newValueAsNum = isNaN(newValue) ? 0 : parseFloat(+newValue), 
      valueToWrite = Math.round(newValueAsNum * roundingMultiplier)/roundingMultiplier; 

      //only write if it changed 
      if (valueToWrite !== current) { 
      target(valueToWrite); 
      } else { 
      //if the rounded value is the same, but a different value was written, force a notification for the current field 
      if (newValue !== current) { 
       target.notifySubscribers(valueToWrite); 
      } 
      } 
     } 
     }).extend({ 
     notify: 'always' 
     }); 

     //initialize with current value to make sure it is rounded appropriately 
     result(target()); 

     //return the new computed observable 
     return result; 
    }; 

    function AppViewModel(one, two) { 
     this.myNumberOne = ko.observable(one).extend({ 
     numeric: 0 
     }); 
     this.myNumberTwo = ko.observable(two).extend({ 
     numeric: 2 
     }); 
    } 

    ko.applyBindings(new AppViewModel(221.2234, 123.4525)); 
    </script> 
0

Ich hatte ein ähnliches Problem.

Ich musste auch nur Inter-Werte sicherstellen, und für IE9 und höher (also Typ = numerical war nicht genug), und da wir viele internationale Kunden haben, konnte ich auch nicht auf Tastencodes verlassen, so ist Folgendes was ich am Ende mit:

//In my js class method (self is this as usual) 
self.ensureNumberical = function (data, e) { 
    var keyValue = e.key; 
    if (keyValue.match(/[0-9]/g)) { 
     return true; 
    } 
    return false; 
} 

//In my MVC View 
data-bind="event: { keypress: ensureNumberical }"