我有一个带有大量小数位的数字的viewModel.如果我的绑定看起来像这样:
<tr>
<td data-bind="text: Date"></td>
<td data-bind="text: ActualWeight"></td>
<td data-bind="text: TrendWeight"></td>
</tr>
Run Code Online (Sandbox Code Playgroud)
然后,当然,输出具有所有小数位并且非常不可读.将绑定更改为这样可以解决问题,但是非常冗长且"嘈杂":
<tr>
<td data-bind="text: Date"></td>
<td data-bind="text: ActualWeight().toFixed(1)"></td>
<td data-bind="text: TrendWeight().toFixed(1)"></td>
</tr>
Run Code Online (Sandbox Code Playgroud)
注意,这是一个小片段,必须添加.toFixed(1)每个我绑定一个数字的位置导致比这里显示的更加凌乱的标记.
对于除数字之外的所有内容,覆盖toString一直是我控制输出内容的有效方法.有关告诉敲门的方法的任何建议,在我的页面的某些中心方式中,在将数字添加到输出之前将数字转换为字符串的功能是什么?
就此而言,有一个通用的方法告诉淘汰赛如何格式化任何类型的值似乎是有用的.重写Date.prototype.toString可以工作,但感觉有点沉重,因为它可能会影响.toString的其他用途除了敲门之外.
RP *_*yer 94
有几种方法可以处理像这样的情况.您可以选择通过绑定来解决它,也可以将其推送到视图模型中.
如果您的视图模型是由映射插件创建的,并且您不希望自定义它的创建方式,那么您可以考虑使用自定义绑定作为文本绑定的包装来处理格式.
像(http://jsfiddle.net/rniemeyer/RVL6q/):
ko.bindingHandlers.numericText = {
update: function(element, valueAccessor, allBindingsAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
precision = ko.utils.unwrapObservable(allBindingsAccessor().precision) || ko.bindingHandlers.numericText.defaultPrecision,
formattedValue = value.toFixed(precision);
ko.bindingHandlers.text.update(element, function() { return formattedValue; });
},
defaultPrecision: 1
};
Run Code Online (Sandbox Code Playgroud)
当然可以创建一个更通用的绑定(formattedText),它检查值并使用一些可覆盖的默认值对其进行格式化,或允许您传递一些格式化选项({ type: "numeric", precision: 2 }).
对于您的场景,听起来第一个选项可能是一个不错的选择.但是,如果要将其推送到视图模型中,则可以创建一个特殊的observable,它可以返回值的格式化和原始版本.
它可能是(http://jsfiddle.net/rniemeyer/fetBG/):
function formattedNumericObservable(initialValue, precision) {
var _raw = ko.observable(initialValue),
precision = precision || formattedNumericObservable.defaultPrecision,
//the dependentObservable that we will return
result = ko.dependentObservable({
read: function() {
return _raw().toFixed(precision);
},
write: _raw
});
//expose raw value for binding
result.raw = _raw;
return result;
}
Run Code Online (Sandbox Code Playgroud)
现在,你可能对绑定myValue,并myValue.raw根据您的需要.否则,您可以将其翻转并默认返回原始值并公开formatteddependentObservable.当像这样的对象转换为JSON时,它将丢失任何"子可观察对象",因此如果您将此数据发送回可能需要考虑的服务器.
您可以再次使其更通用,并创建一个formattedObservable接收有关如何格式化对象的一些信息.
最后,1.3 beta提供了一个extendersAPI.你可以做类似上面的事情:(http://jsfiddle.net/rniemeyer/AsdES/)
ko.extenders.numeric = function(target, precision) {
var result = ko.dependentObservable({
read: function() {
return target().toFixed(precision);
},
write: target
});
result.raw = target;
return result;
};
Run Code Online (Sandbox Code Playgroud)
然后,将其应用于以下观察者: var myValue = ko.observable(1.223123).extend({numeric: 1});
你可以让extender也只是添加一个formatteddependentObservable target而不是返回dependentObservable本身.
mol*_*arg 22
由于knockout现在支持扩展器,我会使用它们而不是自定义绑定.绑定看起来像这样:
<tr>
<td data-bind="text: Date.extend({format : 'date'})"></td>
<td data-bind="text: ActualWeight.extend({format : 'weight'})"></td>
<td data-bind="text: TrendWeight.extend({format : 'weight'})"></td>
</tr>
Run Code Online (Sandbox Code Playgroud)
format在这种情况下你必须编写扩展器.淘汰文档中提供了示例.
小智 10
为了格式化货币和百分比,我创建了自定义绑定数字格式.js,用于在http://adamwdraper.github.com/Numeral-js/上找到的numeral.min.js.
数字格式.js(灵感来自dateformat.js和moment.min.js)
var formatNumber = function (element, valueAccessor, allBindingsAccessor, format) {
// Provide a custom text value
var value = valueAccessor(), allBindings = allBindingsAccessor();
var numeralFormat = allBindingsAccessor.numeralFormat || format;
var strNumber = ko.utils.unwrapObservable(value);
if (strNumber) {
return numeral(strNumber).format(numeralFormat);
}
return '';
};
ko.bindingHandlers.numeraltext = {
init: function (element, valueAccessor, allBindingsAccessor) {
$(element).text(formatNumber(element, valueAccessor, allBindingsAccessor, "(0,0.00)"));
},
update: function (element, valueAccessor, allBindingsAccessor) {
$(element).text(formatNumber(element, valueAccessor, allBindingsAccessor, "(0,0.00)"));
}
};
ko.bindingHandlers.numeralvalue = {
init: function (element, valueAccessor, allBindingsAccessor) {
$(element).val(formatNumber(element, valueAccessor, allBindingsAccessor, "(0,0.00)"));
//handle the field changing
ko.utils.registerEventHandler(element, "change", function () {
var observable = valueAccessor();
observable($(element).val());
});
},
update: function (element, valueAccessor, allBindingsAccessor) {
$(element).val(formatNumber(element, valueAccessor, allBindingsAccessor, "(0,0.00)"));
}
};
ko.bindingHandlers.percenttext = {
init: function (element, valueAccessor, allBindingsAccessor) {
$(element).text(formatNumber(element, valueAccessor, allBindingsAccessor, "(0.000 %)"));
},
update: function (element, valueAccessor, allBindingsAccessor) {
$(element).text(formatNumber(element, valueAccessor, allBindingsAccessor, "(0.000 %)"));
}
};
ko.bindingHandlers.percentvalue = {
init: function (element, valueAccessor, allBindingsAccessor) {
$(element).val(formatNumber(element, valueAccessor, allBindingsAccessor, "(0.000 %)"));
//handle the field changing
ko.utils.registerEventHandler(element, "change", function () {
var observable = valueAccessor();
observable($(element).val());
});
},
update: function (element, valueAccessor, allBindingsAccessor) {
$(element).val(formatNumber(element, valueAccessor, allBindingsAccessor, "(0.000 %)"));
}
};
Run Code Online (Sandbox Code Playgroud)
View中的绑定示例.
<td><label>Available Commitment Balance:</label> </td>
<td>
<!-- ko with: SelectedLoan -->
<span data-bind="numeraltext: AvailableCommitmentAmount"></span>
<!-- /ko -->
</td>
<td><label> % Interest Rate:</label></td>
<td>
<!-- ko with: SelectedLoan -->
<input data-bind="percentvalue: InterestRatePercent" />
<!-- /ko -->
</td>
<td><label> $ Amount To Transfer:</label></td>
<td>
<!-- ko with: SelectedLoan -->
<input class="inputsmall" data-bind="numeralvalue: FundsHeldTotalAmount" />
<!-- /ko -->
</td>
Run Code Online (Sandbox Code Playgroud)
小智 9
建立在上面接受的答案之上.我分叉RP Niemeyers小提琴添加逗号格式.所以,如果你有10001.232,这将格式化为10,001.232.如果您正在处理价格,这非常重要.同样,这只是建立在答案的基础上.
<div data-bind="numericText: myValue"></div>
<div data-bind="numericText: myValue, positions: 3"></div>
<div data-bind="numericText: myValue, positions: myPositions"></div>
<input data-bind="value: myPositions" />
<div>
<br>
just testing commas<br>
<input type=text id="withComma" readonly/>
</div>
Run Code Online (Sandbox Code Playgroud)
ko.bindingHandlers.numericText = {
update: function(element, valueAccessor, allBindingsAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
var positions= ko.utils.unwrapObservable(allBindingsAccessor().positions) || ko.bindingHandlers.numericText.defaultPositions;
var formattedValue = value.toFixed(positions);
var finalFormatted = ko.bindingHandlers.numericText.withCommas(formattedValue);
ko.bindingHandlers.text.update(element, function() { return finalFormatted ; });
},
defaultPositions: 2,
withCommas: function(original){
original+= '';
x = original.split('.');
x1 = x[0];
x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
return x1 + x2;
}
};
var viewModel = {
myValue: ko.observable(12673.554),
myPositions: ko.observable(4)
};
ko.applyBindings(viewModel);
/*Just testing the function below, you don't need thsi....*/
function addCommas(nStr)
{
nStr += '';
x = nStr.split('.');
x1 = x[0];
x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
return x1 + x2;
}
var formatted = addCommas('1070781.493')
$('#withComma').val(formatted);
Run Code Online (Sandbox Code Playgroud)