2

以前はビュー モデルの監視可能なプロパティに直接バインドされていたチェックボックスがあります。すべてのビュー モデルで汎用のダーティ フラグを使用して、ビュー モデルのすべての監視可能なプロパティの変更を監視します。

ここで、あるプロパティについて、基になるオブザーバブルの設定を解除する前にユーザーがチェックボックスをオフにしようとした場合に確認アラートを表示したいと考えています。私はこれを次のようにオブザーバブルをラップする書き込み可能な計算オブザーバブルとして実装しようとしました:

function VM() {
    var self = this;

    self.SelectedInternal = ko.observable(false);

    self.selected= ko.computed({
        read: function () {
            return self.SelectedInternal();
        },
        write: function (value) {
            alert('Clicked'); // To demonstrate problem
            if (value === false) {
                if (confirm('Are you sure you wish to deselect this option?')) {
                    self.SelectedInternal(value);
                }          
            }
        }
    });
}

var vm = new VM();

ko.applyBindings(vm);

(Firefox と IE の両方で) 私が見ているのは、上記のように SelectedInternal オブザーバブル値を false にデフォルト設定すると、「選択された」書き込み関数は、チェックボックスをオフにしたときではなく、チェックボックスをオンにするたびにのみ起動することです。SelectedInternal オブザーバブル値を true にデフォルト設定すると、最初にチェックを外したときに書き込みセッターが実行されますが、その後のチェック解除では実行されません。

デモ用のフィドルを次に示します。

http://jsfiddle.net/xHqsZ/18/

ここで何が起きてるの?これを達成するためのより良い方法はありますか?

更新:元のクリックにフックを付けて false を返すことができないため、このアプローチはおそらくうまくいかないでしょう。ユーザーが確認ボックスでキャンセルを選択した場合、オブザーバブルを true にリセットしても効果。しかし、計算されたセッター自体が期待どおりに動作しない理由を知りたいです。

4

4 に答える 4

2

私はこれまでにこれを達成しました(簡単にするためにプロパティの名前を変更しました):

<input type="checkbox" data-bind="checked: vm.optionComputed, click: vm.toggleOption" />

そしてビューモデルでは:

self.optionComputed = ko.computed({
    read: function () {
        return self.Option();
    },
    write: function (value) {
    }
});

self.toggleOption = function (vm, event) {
    var checkBox = $(event.target);
    var isChecked = checkBox.is(':checked');

    if (!(!isChecked && !confirm('Are you sure?'))) {
        self.Option(isChecked);
    }    
};

[OK]を選択して選択を解除すると、チェックボックス(クリックによって既に空白になっている)が一時的にチェックされてから、最後にチェックを外すというわずかな不具合があります。しかし、確認が正しくなるまで、観測可能な変化を防ぐという観点からの振る舞い。

于 2012-12-12T02:41:56.003 に答える
1

http://knockoutjs.com/documentation/computedObservables.htmlのドキュメントをご覧ください。

書き込み関数は、読み取り関数の値が変更されたときに呼び出されます。ドキュメントの例 #1 を参照してください。

write 関数で行ったことの 1 つは、他の監視可能な値を設定することです。たとえば、1 つのチェック ボックスでグループ内の他のすべてのチェック ボックスをオフにします。書き込み関数内のオブザーバブルを更新するだけでこれを行いました。


編集

最後の段落で説明されていることを行う方法を示すフィドルをまとめました - http://jsfiddle.net/photo_tom/xHqsZ/22/。それを機能させる計算関数は

self.clearAll = ko.computed({
    read: function() {
        return !(self.option1() || self.option2() || self.option3());
    },
    write: function(value) {
        alert('Clicked');
        self.option1(false);
        self.option2(false);
        self.option3(false);

    }
});

編集#2 falseからtrueのチェック状態の質問を手動で確認したいというコメントに答えるには。

これを処理する最もクリーンな方法は、カスタム バインダーを使用することです。重要なセクションは、カスタム変更イベント ハンドラーの登録です。その関数内で、ユーザーが本当にチェックボックスを true に設定したいかどうかを尋ねることができます。

ko.bindingHandlers.checkConfirm = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

        //handle the field changing
        ko.utils.registerEventHandler(element, "change", function() {
            // get the current observable value.
            var value = valueAccessor();
            var valueUnwrapped = ko.utils.unwrapObservable(value);

            if (!valueUnwrapped && element.checked) {
                var r = confirm("Confirm Setting value to true");
                if (r) {
                    value(true);
                    return;
                } else {
                    // not okayed, so clear cb.
                    element.checked = false;
                }
            }
            value(false);
        });
    },
    update: function(element, valueAccessor) {
        // use default ko code to update checkbox
        ko.bindingHandlers.checked.update(element, valueAccessor);
    }
};

更新されたフィドルはhttp://jsfiddle.net/photo_tom/xHqsZ/32/にあります

于 2012-12-10T01:00:40.850 に答える