2013-06-11 3 views
17

я прочитал много учебников, но я не знаю, как это сделать, это входсделать вход только-числовой тип на нокауте

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

и это мой ViewModel

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

, но это причина ошибки: у этого нет метода замены ??? как я могу передать значение цены на вычисленную функцию?

+1

Вместо 'input type =" text "', что, если вы измените его на 'input type =" number "'? Я думаю, что они ограничивают то, что вы вложили в них только числовые значения. – jonhopkins

+3

type = «number» имеет меньшую совместимость с некоторыми браузерами. – andrescabana86

+1

Джон прав, потому что вы можете изменить тип на число, но если я правильно помню, не все браузеры поддерживают этот тип. Например, я считаю, что что-либо перед тем, как IE10 позволит вам помещать текст туда без проблем –

ответ

37

Лучше создать пользовательскую привязку http://knockoutjs.com/documentation/custom-bindings.html, которая допускает только допустимые символы [0-9.] Как числовое представление.

поставить эту строку в ваш взгляд

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

поставить эту строку в модель (не забудьте связать число как наблюдаемом собственности)

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

Действительно ли это работает? Для меня он не обновляет Observable, если он находится где-то в пользовательском интерфейсе? Например, у вас есть , как указано выше, а также некоторые . В этом случае, если пользователь редактирует номер внутри ввода, пользовательский интерфейс не обновляется после завершения редактирования. – renathy

+0

Изменения будут применены после изменения фокуса из поля ввода. Вот простой пример с живым редактированием (без изменения фокуса). http://jsfiddle.net/jakethashi/L7UEm/ –

+0

@renathy Я оставил textInput привязку и добавил числовое значение как второе связывание, отлично работает – LobsterMan

1

Альтернативный подход: я обнаружил, что Knockout работает хорошо в сочетании с jQuery-validate. Вам просто нужно убедиться, что вы проверяете форму, прежде чем пытаться использовать числовое значение.

Скажем у вас есть форма DOM элемент, вы можете настроить правила проверки с помощью

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

В вашей ViewModel вы установили двустороннюю привязку, как обычно, например, через self.year = ko.observable(""). Теперь убедитесь, что вы звоните $(".yourform").valid() перед дальнейшей обработкой self.year(). В моем случае я делаю var year = parseInt(self.year(), 10). Сразу после проверки формы это, как ожидается, всегда приведет к содержательному результату.

7

Нокаут имеет удлинители для этого. Check This от knockoutjs.com, объясняя, как использовать наблюдаемые расширители, чтобы заставить ввод быть числовым. Я вставить код из документации здесь:

Исходный код: Вид

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

Исходный код: Просмотр модели

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 функции и добавить, что.

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

Это будет работать!

-1

Я знаю, что этот вопрос - год, но позвольте мне опубликовать это для посетителя страницы.

Проверьте это:

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

Создание вам данных привязку указывая на свой блестящий новый код:

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

Блестящий новый код Нокаут:

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

Это означает, что каждый время, когда вы обновляете цену, оно будет применять логику в функции (в этом случае вычеркивая все, что есть не число или период), и применять его непосредственно к цене. Вы также можете добавить другие валидации или интересные функции здесь, например, добавить валютный сибмол в начале, сохранить его до двух знаков после запятой и т. Д.

0

С помощью события «keydown» мы можем ограничить использование других клавиш в тексте который должен содержать числовые значения.

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

Мы можем ограничить пользователя вводным пользователем более двух десятичных чисел Ex. 23.81, 3452.83 Измененный код выглядит следующим образом. Код ссылки берется из ответа @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

У меня была аналогичная проблема.

Мне также нужно было обеспечить только значения inter, а для IE9 и выше (поэтому type = numberical было недостаточно), и поскольку у нас много международных клиентов, я тоже не могу полагаться на коды клавиш, так что что я закончил с:

//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 }" 
Смежные вопросы