1

私はノックアウトに慣れていないので、それをうまく処理する方法をまだ学んでいます。アプリには、リアルタイムで更新される一連の計算に関連付けられている入力フィールドがいくつかあります。フィールド自体はうまく機能し、すべて問題ありません...

例外として、ユーザーが入力した入力を表示専用にフォーマットする必要があります (生データは計算のために保持する必要がありますが、3 は 3% として表示されるか、別のフィールドでは 3000000 は 3,000,000 などとして表示される必要があります)。これはある程度機能していますが、結果が一貫してバグであり、入力フィールドを完全に壊す可能性があるため、私のソリューションには大きな欠陥があると思います。

したがって、常に 100% になるように別のフィールドに関連付けられている入力フィールドの 1 つの例を次に示します。

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

したがって、ここで何が起こるかというと、ユーザーが最初に入力した文字は正しく書式設定され、ユーザーが入力した 2 番目の文字は消え、3 番目は最初の文字と結合して正しく書式設定されます。これは、フィールドが計算された場合または通常のオブザーバブルである場合と同じように発生し、計算されたコードは拡張を適用しなくても正常に機能します。したがって、77% を入力するには、7 - X - 7 と入力する必要があります (X は、プロセスのどこかで失われるため、任意の値にすることができます)。

また、このアプリでは仮想 JavaScript 数値キーボードを使用しているため、JavaScript を介して値を追加していることにも注意してください (ただし、これは他の機能には影響していないため、ここで追加する理由はわかりません)。

私が間違っていることについて誰かが提案できますか? 入力が非常にバグる原因となっているのは何ですか? 私は、このリアルタイム入力フォーマットの概念を捨てないことを強く決意していますが、そうする必要がある場合は、ぼかしをフォーマットするだけです。

ご提案いただきありがとうございます。

4

2 に答える 2

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());

http://jsfiddle.net/jschevling/mwbzp55t/

于 2015-05-30T18:53:11.017 に答える
0

入力時に入力内容が書式設定機能によって置き換えられると、カーソルを適切に配置するのが難しいため、2 つのモードを持つフィールドを用意することをお勧めします。フォーマットされた値。どの表示がカーソルのフォーカスに依存します。

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

于 2015-05-27T17:54:08.667 に答える