2017-09-28 10 views
1

現在、Extenderを使用してKnockout JSアプリケーションで自動保存機能を実装しようとしています。ユーザーがフィールドから抜けるときだけでなく、フィールドの入力をやめるときにオートセーブ機能を呼びたいと思います。タイムアウト後にKnockout JS Extender関数を呼び出す

これは、観測値が更新されたときに呼び出すlogChangeメソッドです。

//KO Extender for logging changes and calling the autosave function 
ko.extenders.logChange = function (target, precision) { 

    //create a writable computed observable to intercept writes to our observable 
    var result = ko.pureComputed({ 
     read: target, //always return the original observables value 
     write: function (newValue) { 
      debugger; 
      var current = target(), 
       valueToWrite = newValue, 
       attName = precision; 

      //only write if it changed 
      if (valueToWrite !== current) { 
       target(valueToWrite); 
       //self.autoSave(attName, target()); 
      } else { 
       //if the rounded value is the same, but a different value was written, force a notification for the current field 
       if (newValue !== current) { 
        target.notifySubscribers(valueToWrite); 
       } 
      } 
     } 
    }).extend({ notify: 'always' }); 

    //initialize with current value to make sure it is rounded appropriately 
    result(target()); 

    //return the new computed observable 
    return result; 

}; 

私はviewmodelでobservableを設定しています。

self.controlCenter = ko.observable().extend({ rateLimit: { timeout: 500, method: "notifyWhenChangesStop" }, logChange: "ControlCenter" }); 

そして、これはその観測可能

<div class="pure-u-1-2 pure-u-md-1-4 pure-u-lg-1-8"> 
         <label for="ddlControlCenter">Jurisdiction</label> 
         <input type="text" class="pure-input-1 full-text" list="controlCenterList" data-bind="textInput: controlCenter" /> 
         <datalist id="controlCenterList" data-bind="foreach: controlCenters"> 
          <option data-bind="value: $data"></option> 
         </datalist> 
        </div> 

のための私のHTMLマークアップでlogChangeメソッドが呼び出されますが、logChangeはキー操作ですぐに呼び出されるようレート制限が適用されているようにそれは見えません。

+0

ここから右のコードを得ましたか。 http://knockoutjs.com/documentation/rateLimit-observable.html あなたのコードを取り出し、 'loggedValues'コードを追加して、それをあなたのcontrolCenters変数に変更しました。 rateLimitの遅延とともに、完全に動作します。 または、デバッガにすぐに当たると言っていますか? – Ray

+0

はい、そのリンクは私がコードを入手した場所です。すぐにkeypressのlogChange関数でデバッガを押すので、私のオートセーブ関数も呼び出されます。ですから、コントロールセンターとして値 "DIABLO"を入力すると、 "D"、 "DI"、 "DIA"などを保存しようとします。私は、自動保存をratelimitの後に呼びたいと思います。 – Colin

+0

すぐにデバッガにヒットしたとしても、ラティメーション後に呼び出されます。さて、私はあなたのコードの残りの部分と、デバッガを除いたものが含まれているコードを投稿します。やってみて。 – Ray

答えて

0

更新:

私は以下のフィディドを更新しました。間違いは、新しい値を更新した直後にlogChange関数の中で関数を呼び出すことでした。しかし、rateLimitのコンセプトは、観測値が変更されたという通知が、の遅延の後にすべてのサブスクライバに送信されるということです。

つまり、観測可能なサブスクライバだけがrateLimitの影響を受け、logChange関数内のものは影響を受けません。だから正しい方法は、加入者の中であなたのautoSave関数を呼び出すことです。

function ViewModel() { 
 
var self = this; 
 
self.autoSave = function(attName, value){ 
 
\t console.log(attName + " is now = " + value); 
 
} 
 
self.precision = ko.observable(); 
 
       ko.extenders.logChange = function (target, precision) { 
 

 
        //create a writable computed observable to intercept writes to our observable 
 
        var result = ko.pureComputed({ 
 
         read: target, //always return the original observables value 
 
         write: function (newValue) { 
 
          
 
          var current = target(), 
 
            valueToWrite = newValue;//, 
 
            self.precision(precision); 
 
            //attName = precision; 
 

 
          //only write if it changed 
 
          if (valueToWrite !== current) { 
 
           target(valueToWrite); 
 
           //self.autoSave(attName, target()); 
 
          } else { 
 
           //if the rounded value is the same, but a different value was written, force a notification for the current field 
 
           if (newValue !== current) { 
 
            target.notifySubscribers(valueToWrite); 
 
       } 
 
      } 
 
     } 
 
    }).extend({ notify: 'always' }); 
 

 
    //initialize with current value to make sure it is rounded appropriately 
 
    result(target()); 
 

 
    //return the new computed observable 
 
    return result; 
 

 
}; 
 

 
self.controlCenter = ko.observable().extend({ rateLimit: { timeout: 500, method: "notifyWhenChangesStop" }, logChange: "ControlCenter" }); 
 
self.controlCenters = ko.observableArray([]); 
 
    this.controlCenter.subscribe(function (val) { 
 
     if (val !== '') 
 
      this.controlCenters.push(val); 
 
      self.autoSave(self.precision(), val); 
 
    }, this); 
 
      } 
 
      
 

 
      ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div class="pure-u-1-2 pure-u-md-1-4 pure-u-lg-1-8"> 
 
      <label for="ddlControlCenter">Jurisdiction</label> 
 
      <input type="text" class="pure-input-1 full-text" list="controlCenterList" data-bind="textInput: controlCenter" /> 
 
      <datalist id="controlCenterList" data-bind="foreach: controlCenters"> 
 
       <option data-bind="value: $data"></option> 
 
      </datalist> 
 
     </div>

+0

あなたの助けていただきありがとうございますが、自動保存機能がまだ呼び出され、rateLimitの後に呼び出されることはありません。 – Colin

+0

あなたはフィドルを提供できますか? – Ray

+0

https://jsfiddle.net/zx1mdbvb/ 私はフィドルにオートセーブ機能を追加しました。私のコードでは、属性名と値をサーバーにポストしていますが、例えば、属性と値をコンソールに記録するだけです。コンソールを開くと、rateLimitの後ではなく、キーが押されているときに書き込まれる値が表示されます。 – Colin

関連する問題