web-dev-qa-db-fra.com

créer un type uniquement numérique sur le knockout

j'ai lu beaucoup de tutoriels mais je ne sais pas comment faire cela, c'est l'entrée

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

et c'est mon point de vue

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

mais cette erreur de cause: cela n'a pas de méthode remplacer ??? Comment puis-je passer la valeur du prix à la fonction calculée?

19
andrescabana86

Il est préférable de créer une liaison personnalisée http://knockoutjs.com/documentation/custom-bindings.html qui n'accepte que les caractères autorisés [0-9 ,.] sous forme de représentation numérique.

mettre cette ligne dans votre vue

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

mettre cette ligne dans votre modèle (n'oubliez pas de lier le numéro en tant que propriété observable)

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();
                }
            }
        });
    }
};
45
Martin Surynek

Knockout a des rallonges pour cela. Cochez cette case de knockoutjs.com expliquant comment utiliser des extensions observables pour forcer l'entrée numérique Je colle le code de la documentation ici:

Code source: Voir

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

Code source: Voir le modèle

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

J'avais un problème similaire.

Je devais également assurer uniquement les valeurs inter, et pour IE9 et les versions ultérieures (le type = numérique n'était donc pas suffisant), et comme nous avons beaucoup de clients internationaux, je ne pouvais pas compter non plus sur les codes clés. avec:

//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 }"
3
Ano nomouis

Une approche alternative: j'ai trouvé que Knockout fonctionne bien en combinaison avec jQuery-validate . Vous devez simplement vous assurer que vous validez le formulaire avant d'essayer d'utiliser la valeur numérique.

Disons que vous avez un élément de formulaire DOM, vous pouvez configurer des règles de validation via

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

Dans votre modèle de vue, vous définissez la liaison bidirectionnelle comme d'habitude, par exemple via self.year = ko.observable(""). Assurez-vous maintenant que vous appelez $(".yourform").valid() avant de poursuivre le traitement de self.year(). Dans mon cas, je fais var year = parseInt(self.year(), 10). Immédiatement après la validation du formulaire, cela devrait toujours produire un résultat significatif.

2
Jan-Philip Gehrcke

Idéal pour le scénario d'aujourd'hui https://github.com/Knockout-Contrib/Knockout-Validation

lancez l'extrait ci-dessous. Si vous entrez un chiffre ou un chiffre supérieur à 255, le message sera affiché.

function model() {
  var self = this;
  this.myObj = ko.observable().extend({ digit: true }).extend({ max: 255});
  }
  
  var mymodel = new model();

$(document).ready(function() {
  ko.validation.init();
  ko.applyBindings(mymodel);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout-validation/2.0.3/knockout.validation.min.js"></script>

enter a digit less than or equal to  255 <input type="text" data-bind="textInput: myObj">

<p>
  Enter something other than a digit or over 255 will cause an error.
</p>

courtoisie: Bryan Dellinger: https://stackoverflow.com/a/42940109/3868653

1
xxbinxx
 <input type="text" id="alpha-validation" data-bind="value: YourDataName, valueUpdate: 'afterkeydown' , event: { 'input': AlphaCheck}" style="text-transform:uppercase">

créez la fonction AlphaCheck et ajoutez-la.

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

Ça va marcher!

1
Hadnazzar

Avec l'aide de l'événement "keydown", nous pouvons restreindre d'autres clés dans la zone de texte qui devrait contenir des valeurs numériques.

$(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
Ananth Cool

Créez votre liaison de données en pointant vers votre nouveau code brillant:

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

Nouveau code KO brillant:

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

Cela signifie que chaque fois que vous mettez à jour le prix, il appliquera la logique de la fonction (en supprimant tout ce qui n'est pas un nombre ou une période) et l'appliquera directement au prix. Vous pouvez également ajouter d’autres fonctionnalités de validation ou intéressantes, telles que l’ajout d’un sybmol de devise au début, son maintien à 2 décimales, etc.

0
TinyDancer

Nous pouvons limiter l'utilisateur à saisir plus de deux nombres décimaux, par ex. 23.81, 3452.83 Le code modifié est comme ci-dessous. Le code de référence provient de la réponse @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
Ravindra Vairagi