我是淘汰赛的新手,并且还在学习如何最好地使用它。我在应用程序中有一些输入字段,它们与一堆实时更新的计算相关联。他们自己的工作很棒,一切都很好......
除了我需要在用户输入时格式化输入,仅用于显示(原始数据必须保留用于计算,但3应显示为3%或在另一个字段3000000应显示为3,000,000等) 。我有点有点工作,但我认为我的解决方案存在一个重大缺陷,因为结果一直是错误的,并且可以完全打破输入字段。
因此,其中一个输入字段的示例与另一个字段相关,始终等于100%:
<input id='sm' data-bind='textInput: s_smixe' readonly='true'>
必然:
self.s_smixebase = ko.observable(30);
self.s_smixe = ko.pureComputed({
read: function(){
return this.s_smixebase();
},
write: function(value){
if (parseFloat(value)<100) {
var otherValue = 100 - parseFloat(value);
this.s_smixebase(value);
this.s_rmixebase(otherValue);
} else {
value = 100;
this.s_smixebase(value);
this.s_rmixebase(0);
}
},
owner: this
}).extend({percent:{}});
self.s_smixeraw = self.s_smixe.raw;
然后通过以下方式扩展:
ko.extenders.percent = function(target) {
var raw = ko.observable();
var result = ko.computed({
read: function() {
var value = target();
if (value.toString().indexOf('%')===-1){
raw(parseFloat(value));
value = value + '%';
return value;
} else {
value = value.replace('%','');
raw(parseFloat(value));
value = value + '%';
return value;
}
},
write: target
}).extend({notify:'always'});
result.raw = raw;
return result;
};
所以,这里发生的是,用户输入的第一个字符格式正确,用户输入的第二个字符消失,第三个字符加入第一个字符并正确格式化。如果计算字段或常规可观察,则发生相同的情况,并且计算出的代码在没有应用扩展的情况下工作正常。因此,要输入77%,您必须键入7 - X - 7(其中X可以是任何值,因为它会在某处丢失进程)。
还应该注意的是,我在这个应用程序中使用虚拟javascript数字键盘,所以我通过javascript添加值(虽然这没有影响任何其他功能,所以我不知道它为什么会这里)。
有人可以提出我做错的建议吗?我错过了什么导致输入如此错误?我真的决定不放弃这种实时输入格式化的概念,因为它可以提供更清晰的演示,但是如果我不得不在模糊上进行格式化。
提前感谢任何建议。
答案 0 :(得分:0)
因为在格式化功能替换你键入的内容时正确定位光标很棘手,我建议你有一个有两种模式的字段:一种是在你输入的模式,另一种是在哪里它显示格式化的值。哪些显示取决于光标焦点。
<div data-bind="with:pctInput">
<label>Value</label>
<input class="activeInput" data-bind='textInput: base, event:{blur:toggle}, visible:editing, hasFocus:editing' />
<input data-bind='textInput: formatted, event:{focus:toggle}, visible:!editing()' readonly='true' />
</div>
这里有一个工作示例: http://jsfiddle.net/q473mu4w/1/
答案 1 :(得分:0)
因此,对于后来遇到这种情况的人来说,我最终使用了初始评论中提到的线程的@RoyJ解决方案的修改版本。如果我要在较大的项目中使用它,我确实需要想出一种方法来制作这种规模,但对于输入数量较少的东西来说它就足够了。此外,在我的情况下,有许多格式化字段根据输入计算它们的值,因此multPercent和multNumber计算值。我想确保所有输入都正确地进行计算。下面是一个代码示例,下面是一个有效的jsfiddle:
<input data-bind="textInput:textPercent" />
<div data-bind="text:multPercent"></div>
<input data-bind="textInput:textNumber" />
<div data-bind="text:multNumber"></div>
以及随附的javascript:
function dataBindings() {
var self = this;
self.percent = function(str){
var splice = str.toString().replace('%','');
splice = splice + '%';
return splice;
};
self.number = function(numStr){
var formatted;
if (Number(numStr) % 1) {
var integer = numStr.toString().replace(/\.\d+/g,'');
var decimal = numStr.toString().replace(/\d+\./g,'');
integer = integer.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,"); //add comma formatting
formatted = integer + '.' + decimal;
console.log('formatted = '+formatted);
return formatted;
} else {
formatted = numStr.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,");
return formatted;
}
};
self.displayPercent = ko.observable('5%');
self.rawPercent = ko.observable(5);
self.formattedPercent = ko.computed({
read: function() {
return self.displayPercent();
},
write: function(newValue) {
if (newValue==='') {
newValue = 0;
self.rawPercent(0);
var f = self.percent(newValue);
self.displayPercent(f);
} else {
if (newValue.charAt(0)==='0') {
newValue = newValue.slice(1);
}
self.rawPercent(parseFloat(newValue.toString().replace('%','')));
var f = self.percent(newValue);
self.displayPercent(f);
}
}
});
self.displayNumber = ko.observable('3,000');
self.rawNumber = ko.observable(3000);
self.formattedNumber = ko.computed({
read: function(){
return self.displayNumber();
},
write: function(newValue) {
if (newValue==='') {
newValue = 0;
self.rawNumber(0);
self.displayNumber('0');
} else {
if (newValue.charAt(0)==='0') {
newValue = newValue.slice(1);
}
newValue = newValue.replace(/(,)+/g,'');
self.rawNumber(parseFloat(newValue));
var n = self.number(newValue);
self.displayNumber(n);
}
}
});
self.multPercent = ko.computed(function(){
return self.percent(self.rawPercent() * self.rawPercent());
});
self.multNumber = ko.computed(function(){
return self.number(self.rawNumber() * self.rawNumber());
});
return {
textPercent: self.formattedPercent,
multPercent: self.multPercent,
textNumber: self.formattedNumber,
multNumber: self.multNumber
};
}
ko.applyBindings(new dataBindings());