2011-09-26 14 views
5

私はデータベースに(OKの)コミットされている場合のみ、フォームにデータを保存するように、従属オブザーバブルでcommit()/ peek()タイプの関数を使用する特別な拡張バージョンのKoを使用しています。キャンセル時に元に戻ります。knockoutJsのチェックボックスがチェックされている場合にのみ書き込まれるのはなぜですか?

問題チェックボックスをオンにすると、保護された監視対象に対して書き込み関数が正しく呼び出されるということがあります。ただし、チェックボックスをオフにすると、書き込み関数は呼び出されないので、モデルがMVCコントローラに送信されると、チェックボックスのブール値はTRUEになります。

ノックアウトがFALSE値を書き込まないのはなぜですか? CODE WITH

UPDATED QUESTION:

証明するために、ここでこのJsFiddleをご覧ください。http://jsfiddle.net/b2Qu2/3/

マイナー問題

デモと1つのその他の問題があることに注意してください - について何らかの理由で、チェックボックスをオンまたはオフにすると、依存しているObservableにチェーンされていても、表示された値はUIで更新されません。 'peek'ボタンをクリックして値を覗くことができます。問題を再現するには

大きな問題

1) Click 'peek' button: Shows FALSE - CORRECT 

2) Check IsAdmin checkbox 

3) Click 'peek' again: Shows TRUE - CORRECT 

4) Uncheck IsAdmin 

5) Click 'peek' again: SHOWS TRUE - INCORRECT!! 

シナリオ例

は、ダイアログが管理者ユーザーのためのチェックボックスで示されている想像してみてください。 adminユーザーは1人しか設定できません。管理ユーザーがすでに存在する場合、サーバーは有効/無効で応答します。 ユーザはチェックボックスのチェックを外しますが、今度はviewmodelはチェックボックスが常にtrueと判断しますか? protectedObservableを使用する理由は、サーバーの応答が成功するとcommit()メソッドが呼び出されるため、すべてがUIに保持されます。ユーザーがダイアログをキャンセルするか、エラーが発生した場合、元の値は上書きされません。

+0

あなたのコードの多くを共有することができ、限り、それがバインドされているかのように/使用? –

+0

@RP Niemeyer - いくつかのコードで質問を更新しました。これで苦労します! – jaffa

答えて

3

書き込みが1つの値に対してのみ実行されるのは、書き込み対象となる値に別の値を書き込む必要があると判断した場合にトリガされるためです。したがって、protectedObservableの実際の値は変更されません。それが真で、それを真に設定しようとすると、正しい値を持っていると考えられるので、書き込みは実行されません。

私はおそらく少しそれを変更し、このようなものを使用します。

ko.protectedObservable = function (initialValue) { 
    //private variables 
    var _actual = ko.observable(initialValue), 
     _temp = ko.observable(initialValue); 

    //access to temp value 
    _actual.temp = _temp; 

    //commit the temporary value to our observable, if it is different 
    _actual.commit = function() {   
     if (_temp() !== _actual()) { 
      _actual(_temp()); 
     } 
    }; 

    //notify subscribers to update their value with the original 
    _actual.reset = function() { 
     _actual.valueHasMutated(); 
     _temp(_actual()); 
    }; 

    return _actual; 
}; 

をあなたはfield1またはfield1.tempに対してバインドすることができます。このバージョンでは。一時的な値と実際の値の両方が観測可能であるため、覗く必要はありません。

それは次のようになります。http://jsfiddle.net/rniemeyer/BwDYE/

+0

こんにちは、ありがとうコード例です。私のコードベース全体は、私の最初のフィドルに基づいてprotectedObservableに基づいているので、その動作/バインディングを変更したいとは思っていません。モデル上のバインディングは、.tempsではなく実際のprotectedObservablesを使用します。あなたの例は、ダイアログボックスがキャンセルされた場合のreset()/成功時のserver errorとcommit()に基づいています。私のモデルは逆数に基づいています。ユーザーがキャンセルした場合、またはサーバーエラーが発生した後、ピーク値がサーバーに送信されるため、何もしません。サーバーが成功したら、commit()を実行します。うーん、これを丸める方法がわからない... – jaffa

+1

私はそれがどう違っているのかよくわからない。 'yourfield'ではなく' yourfield.temp'に全てをバインドするだけです。同じように動作する必要があります。あなたのシナリオではうまくいかないことがわかりましたか?適切な選択肢を思いつくのを手伝ってくれることを嬉しく思うでしょう。 –

+1

チェックボックスdepedentObservableの値が、元の値から変更されているかどうかに関係なく常に書き込まれるようにする方法はありますか?これは問題で、元の回答と結びついているようです。私は元のコードのwrite関数にデバッグステートメントを入れて、チェックボックスの値が元の値と逆の場合にのみ呼び出されます。これが解決できれば私のすべてのビューを.tempsに置き換える必要はありません。これが理にかなってほしい!あなたが考えていることが最善の方法であることを私に教えてください。 – jaffa

関連する問題