2状态带有knockoutjs的圆形数字文本框

时间:2017-01-16 11:57:49

标签: javascript jquery html knockout.js textbox

我想要一个带有2个状态的html数字文本框,当聚焦时,它必须显示所有小数位,并且当焦点丢失时,只显示2个小数。我几乎实现了它。

HTML:

<input data-bind="attr: { 'data-numericvalue': valueToRound}" class="numerictextbox"
       type="number"/>

使用Javascript:

var viewModel = {
    valueToRound: ko.observable(7.4267),
};

//NUMERIC TEXTBOX BEHAVIOUR
$('.numerictextbox').focusout(function () {
  $(this).attr("data-numericvalue", this.value); //this line does not update the viewModel
  this.value = parseFloat($(this).attr("data-numericvalue")).toFixed(2);
});
$('.numerictextbox').focusin(function () {
  if ($(this).attr("data-numericvalue") !== undefined) this.value = $(this).attr("data-numericvalue");
});

ko.applyBindings(viewModel); 

Jsfiddle:https://jsfiddle.net/7zzt3Lbf/64/

但我的问题是,当焦点发生时,它不会更新绑定属性,在这种情况下为viewModel。这是我的代码的简化版本,所以我希望它在我的真实场景中对很多属性都是通用的。

1 个答案:

答案 0 :(得分:4)

你混合了太多的jQuery:)

Knockout具有event绑定和hasFocus绑定来处理UI输入。

在下面的示例中,我创建了一个viewmodel,它具有隐藏的realValue observable,用于存储未修改的输入。当displayValue为false时,showDigits会将此数字限制为2位数字。

我使用hasFocus来跟踪我们是否要显示整数:它与showDigits相关联。

var ViewModel = function() {
  this.showDigits = ko.observable(true);
  
  var realValue = ko.observable(6.32324261);

  this.displayValue = ko.computed({
    read: function() {
      return this.showDigits() 
        ? realValue()
        : parseFloat(realValue()).toFixed(2);
    },
    write: realValue
  }, this);
};


ko.applyBindings(new ViewModel()); 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input data-bind="value: displayValue, hasFocus: showDigits" type="number"/>

编辑:在评论计算出的额外代码太多之后:这里是如何将计算逻辑包装在可重用的扩展器中:

ko.extenders.digitInput = function(target, option) {
  var realValue = target,
      showRealValue = ko.observable(false),
      displayValue = ko.computed({
        read: function() {
          return showRealValue() 
            ? realValue()
            : parseFloat(realValue()).toFixed(2);
        },
        write: realValue
      }, this);
  
  displayValue.showRealValue = showRealValue;
  
  return displayValue;
};


var ViewModel = function() {
  this.value1 = ko.observable(6.452345).extend({ digitInput: true });
  this.value2 = ko.observable(4.145).extend({ digitInput: true });
};


ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<input data-bind="value: value1, hasFocus: value1.showRealValue" type="number"/>
<input data-bind="value: value2, hasFocus: value2.showRealValue" type="number"/>