在可观察字段中显示 $ 符号 Knockout

Display $ sign in observable fields Knocout

在我的 MVC 项目中,我有一个包含 3 个计算器的视图,每个计算器都有自己的表单,我有一个用于所有 3 个表单的视图模型,视图模型包含多个计算字段,并且这些字段相互依赖。

我正在寻找向所有字段添加 $ 符号的方法,我只需要它来将它显示给客户端,然后在 javascript/KO 代码中删除它(我可以' t 对带有 $ 符号的计算字段进行计算)。

我写了下面的函数:

this.formatCurrency = function (value) {
    if (value && value !== "") {
        value = value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
        return "$" + value;
    }
}

但是我必须从每个字段调用这个函数:

<span data-bind='text: formatCurrency(improvements())'>

并且还要在计算的任何计算之前删除 $ 符号。

有没有人知道如何做到这一点?我什么都没想到..

文档中有一个示例在 "real" 数值之上使用 ko.pureComputed 层:

this.price = ko.observable(25.99);

this.formattedPrice = ko.pureComputed({
    read: function () {
        return '$' + this.price().toFixed(2);
    },
    write: function (value) {
        // Strip out unwanted characters, parse as float, then write the 
        // raw data back to the underlying "price" observable
        value = parseFloat(value.replace(/[^\.\d]/g, ""));
        this.price(isNaN(value) ? 0 : value); // Write to underlying storage
    },
    owner: this
});

来源:http://knockoutjs.com/documentation/computed-writable.html

这允许您在数据绑定中使用 formattedPrice,您甚至可以写入它。 price 将保留一个数字。不过,您的视图模型中每个数字都需要一个额外的 属性...

如果您只是追求单向绑定,您还可以创建一个扩展 text 绑定的 currencyFormatter 绑定:

var formatCurrency = function(value) {
  value = parseFloat(("" + value).replace(/[^\.\d]/g, ""));
  return "$" + (isNaN(value) ? 0 : value);
}

ko.bindingHandlers.currencyText = {
  update: function(element, valueAccessor) {
    var originalValue = ko.unwrap(valueAccessor());
    var formatValue = formatCurrency.bind(null, originalValue);
    ko.bindingHandlers.text.update.call(null, element, formatValue);
  }
};


ko.applyBindings({
  source: ko.observable(1)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<input type="number" step="0.1" data-bind="value: source">
<h1 data-bind="currencyText: source"></h1>

感谢@user3297291 的回答,我知道了如何去做。

我有以下 bindingHandler 来处理我的数值:

ko.bindingHandlers.numValue = {
init: function (element, valueAccessor) {
    function numValueHandler() {
        valueAccessor()(this.value);
    }
    $(element).on("input change", numValueHandler)
              .val(ko.unwrap(valueAccessor()));
    ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
        $(element).off("input change", numValueHandler);
    });
},
update: function (element, valueAccessor) {
    element.value =ko.unwrap(valueAccessor());
}
};

我添加了这一行以在获取值时删除 $ 符号:

parseFloat(("" + this.value).replace(/[^\.\d]/g, ""))

并在将其发送回视图之前添加了一个 $ 符号:

 element.value ='$' + ko.unwrap(valueAccessor());

所以整个 bindingHandler 看起来像这样:

ko.bindingHandlers.numValue = {
init: function (element, valueAccessor) {
    function numValueHandler() {
        valueAccessor()(parseFloat(("" + this.value).replace(/[^\.\d]/g, "")));
    }
    $(element).on("input change", numValueHandler)
              .val(ko.unwrap(valueAccessor()));
    ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
        $(element).off("input change", numValueHandler);
    });
},
update: function (element, valueAccessor) {
    element.value ='$' + ko.unwrap(valueAccessor());
}
};

电话是:

<input type="text" data-bind="numValue: improvements" />
<input type="text" data-bind="numValue: improvements2" />
//etc..

效果很好,无需在每个字段上调用 ​​formatCurrency 函数并使用几行代码。

感谢@user3297291 的帮助!