2014-12-09 3 views
1

Я знаю, что меня интересуют варианты этого вопроса, но мое требование состоит в том, что вместо форматирования/округления введенного значения мне не нужно даже позволять пользователю вводить более одного числа после десятичной точка. У меня есть что-то, что работает с обработчиком привязки decimalFormatter, но оно неуклюже - то есть оно позволяет вводить значение типа «20». и вы не можете стереть все значения из-за того, как я записал регулярное выражение. Я понимаю, что могу изменить это, чтобы принимать необязательные цифры для всей записи, но я действительно хочу, чтобы она вернулась к 0.0, если пользователь стирает значение. И разрешите им войти в «20». затем перейдите на вкладку (onblur) и переформатируйте значение до 20.0, чтобы он выглядел более полным. В настоящее время, если пользователь вводит «20». затем сохраняет форму, она сохраняет целое значение 20, и когда вы снова открываете/извлекаете значение из базы данных, оно показывает 20.0, поэтому при перезагрузке оно выглядит отлично.KnockoutJS перехват с точностью до одного десятичного знака

Я думал о добавлении события onblur, но мы не хотим этого делать, переопределяя то, что было привязано к нокауту. Мы хотим сохранить все, связанное с моделью просмотра ko, так что это не вариант. Я также видел, что некоторые предлагают вычисляемые наблюдаемые (например, это SO post), но моя привязка уже делает это. С другой стороны, был бы нокаут event binding?

HTML:

<input style="width:38px" data-bind="decimalFormatter: percentage"/> 

JavaScript:

ko.bindingHandlers.decimalFormatter = { 
    init: function (element, valueAccessor) { 
    var initialValue; 

    //$(element).on('keydown', function (event) { 
    $(element).keydown(function (event) { 
     initialValue = $(element).val(); 

     // 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 combinations 
     (event.ctrlKey === true) || 
     // Allow decimal/period 
     (event.keyCode === 110) || (event.keyCode === 190) || 
     // 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(); 
      } 
     } 
    }); 

    $(element).keyup(function (event) { 
     if (!$(element).val().match(/^\d+\.?\d?$/)) { 
      event.preventDefault(); 
      $(element).val(initialValue); 
     } 
     else 
      return; 
    });   

    var observable = valueAccessor(); 

    var interceptor = ko.computed({ 
     read: function() { return formatWithComma(observable(), 1); }, 
     write: function (newValue) { 
      observable(reverseFormat(newValue, 1)); 
     } 
    }); 

    if (element.tagName == 'INPUT') 
     ko.applyBindingsToNode(element, { value: interceptor }); 
    else 
     ko.applyBindingsToNode(element, { text: interceptor }); 
    }, 
    update: function (element, valueAccessor) { 
    } 
} 

// Formatting Functions 
function formatWithComma(x, precision, seperator) { 
    var options = { 
     precision: precision || 2, 
     seperator: seperator || '.' 
    } 
    var formatted = parseFloat(x, 10).toFixed(options.precision); 
    var regex = new RegExp('^(\\d+)[^\\d](\\d{' + options.precision + '})$'); 
    formatted = formatted.replace(regex, '$1' + options.seperator + '$2'); 
    return formatted; 
} 

function reverseFormat(x, precision, seperator) { 
    var options = { 
     precision: precision || 2, 
     seperator: seperator || '.' 
    } 

    var regex = new RegExp('^(\\d+)[^\\d](\\d+)$'); 
    var formatted = x.replace(regex, '$1.$2'); 
    return parseFloat(formatted); 
} 

var viewModel = function() { 
    var self = this; 
    self.percentage = ko.observable(20.0); 
}; 

var vm = new viewModel(); 
ko.applyBindings(vm); 

JSFiddle

+0

Фигурные скобки из равновесия. –

+0

достаточно справедливо - исправлено. Обычно я вывожу код из Visual Studio, вставляю его в текстовую панель, переписываю все, а затем заменяю вкладку четырьмя пробелами, чтобы удовлетворить требование SO с кодом с четырьмя пробелами. Есть ли более простой способ? – sfors

+0

Я тоже схожу в Notepad ++, который кодирует цвет текста, упрощающий сопоставление открывающих и закрывающих скобок, а также поиск опечаток в именах переменных и т. Д. И т. Д. Возможно, Textpad делает то же самое, но я не использовал его. –

ответ

4

Ну я использовал AUTONUMERIC плагин для форматирования чисел, который был надежным и удивительным.

Я только что сделал образец скрипку вашему требованию проверить его here

вид Модель:

var vm = function(){ 
this.Amount=ko.observable(""); 
this.OnloadAmount=ko.observable(143); //onLoad Test 
ko.bindingHandlers.autoNumeric = { 
     init: function (el, valueAccessor, bindingsAccessor, viewModel) { 
      var $el = $(el), 
       bindings = bindingsAccessor(), 
       settings = bindings.settings, 
       value = valueAccessor(); 

      $el.autoNumeric(settings); 
      $el.autoNumeric('set', parseFloat(ko.utils.unwrapObservable(value()), 10)); 
      $el.change(function() { 
       value(parseFloat($el.autoNumeric('get'), 10)); 
      }); 
     }, 
     update: function (el, valueAccessor, bindingsAccessor, viewModel) { 
      var $el = $(el), 
       newValue = ko.utils.unwrapObservable(valueAccessor()), 
       elementValue = $el.autoNumeric('get'), 
       valueHasChanged = (newValue != elementValue); 

      if ((newValue === 0) && (elementValue !== 0) && (elementValue !== "0")) { 
       valueHasChanged = true; 
      } 

      if (valueHasChanged) { 
       $el.autoNumeric('set', newValue); 
      } 
     } 
    }; 
} 

    ko.applyBindings(new vm()); 

Вид:

<input type="text" data-bind="autoNumeric:$data.Amount, settings:{mDec:1,aSep: ''} " /> 

Здесь mDec:1 ограничивает число в десятичную Palce одного и asep:'' означает, что он не будет отбирать номер запятыми и т. Д.

PS: Мы можем ограничить ввод недействительных символов и делать много других вещей с легкостью.

Для полной проверки справочном here

+1

это супер круто, sc! Спасибо за помощь.Похоже, он отлично работает без драмы. Nice .. – sfors

+0

рад, что это помогает. изучите больше опций (при необходимости) его замечательный плагин. –

+0

На самом деле, я использовал супермаленькую библиотеку accounting.js 4KB (http://openexchangerates.github.io/accounting.js/), но довольно уверен, что она не делает все, что нам нужно, чтобы соответствовать чертам autonumeric для создания этого обработчика привязки. Вместо того, чтобы использовать две библиотеки, я рассмотрю их, чтобы проверить, могу ли я переустановить ваш bindHandler, чтобы, возможно, использовать accounting.js только потому, что он меньше. Если это не сработает, я сброшу account.js. – sfors

Смежные вопросы