Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/439.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 淘汰扩展问题-更好的解决方案?_Javascript_Knockout.js_Knockout Extensions - Fatal编程技术网

Javascript 淘汰扩展问题-更好的解决方案?

Javascript 淘汰扩展问题-更好的解决方案?,javascript,knockout.js,knockout-extensions,Javascript,Knockout.js,Knockout Extensions,我是新手,还在学习如何最好地使用它。我在一个应用程序中有几个输入字段,这些字段与一系列实时更新的计算相关联。田里的庄稼长得很好,一切都很好 除此之外,我需要在用户输入时格式化输入,仅用于显示(原始数据必须保留用于计算,但3应显示为3%,或在另一个字段中,3000000应显示为3000000等)。这在某种程度上是可行的,但我认为我的解决方案存在一个主要缺陷,因为结果始终是错误的,并且有可能完全破坏输入字段 例如,一个输入字段与另一个字段关联,始终等于100%: <input id='sm'

我是新手,还在学习如何最好地使用它。我在一个应用程序中有几个输入字段,这些字段与一系列实时更新的计算相关联。田里的庄稼长得很好,一切都很好

除此之外,我需要在用户输入时格式化输入,仅用于显示(原始数据必须保留用于计算,但3应显示为3%,或在另一个字段中,3000000应显示为3000000等)。这在某种程度上是可行的,但我认为我的解决方案存在一个主要缺陷,因为结果始终是错误的,并且有可能完全破坏输入字段

例如,一个输入字段与另一个字段关联,始终等于100%:

<input id='sm' data-bind='textInput: s_smixe' readonly='true'>
因此,这里发生的是,用户输入的第一个字符正确格式化,用户输入的第二个字符消失,第三个字符正确地连接第一个字符和格式。如果场是计算的或常规的可观测的,并且计算代码在没有应用扩展的情况下运行良好,则会发生同样的情况。因此,要输入77%,您必须键入7-X-7(其中X可以是任何值,因为它会丢失到进程的某个地方)

还应该注意的是,我在这个应用程序中使用了一个虚拟javascript数字键盘,所以我通过javascript添加值(尽管这没有影响任何其他功能,所以我不确定为什么会在这里)

有人能就我做错了什么提出建议吗?我遗漏了什么导致输入如此错误?我真的决定不抛弃这种实时输入格式的概念,因为它有助于更清晰的表示,但如果必须的话,我会在模糊上格式化


提前感谢您的建议。

因为当格式化函数替换您键入的内容时,要正确定位光标是很困难的,所以我建议使用一个具有两种模式的字段:一种是在其中键入,另一种是在其中显示格式化值。显示什么取决于光标焦点

<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>

价值
下面是一个工作示例:

因此,对于后来遇到这个问题的人,我最终使用了@RoyJ解决方案的一个修改版本,该版本来自最初评论中提到的线程。如果我打算在更大的项目中使用它,我确实需要想出一种方法来实现这种规模,但是对于一些只有少量输入的项目来说,它已经足够了。此外,在我的例子中,有许多格式化字段根据输入计算它们的值,因此是multPercent和multNumber计算值。我想确保所有的输入都能正确地进行计算。下面是一个使用JSFIDLE的代码示例:

<input data-bind="textInput:textPercent" />
<div data-bind="text:multPercent"></div>
<input data-bind="textInput:textNumber" />
<div data-bind="text:multNumber"></div>

我做了一个。。。虽然我没有使用虚拟键盘,但它似乎运行正常。因此,除非我曲解了你的意图,否则在那把小提琴中,问题可能出在键盘上?@Retsam这几乎是一样的,只有这个应用程序中的输入字段也是显示字段(因此s_smixebase不显示,s_smixe绑定到活动输入字段),所以我在字段中输入时对输入进行格式化。但是知道它是独立工作的,这是非常有帮助的!谢谢你!我将继续讨论,看看键盘是否是问题所在。这不应该在扩展器中完成,而应该是绑定处理程序。当您想要扩展可观察对象的功能时,应该使用扩展器。当您想改变与绑定处理程序的交互方式时,应该使用绑定处理程序。@jeffmercadoah-ha!好啊那么,关于这个问题。由于我需要textInput的功能(即时更新等),我如何最好地增强它/什么是最佳实践?您想要做的与本问题中讨论的非常相似:请注意,当您重新格式化输入内容时,光标位置可能会带来困难。
<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>
<input data-bind="textInput:textPercent" />
<div data-bind="text:multPercent"></div>
<input data-bind="textInput:textNumber" />
<div data-bind="text:multNumber"></div>
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());