2012-05-02 15 views
5

オートコンプリートを処理するためのカスタムバインディングがあります。ユーザーがオートコンプリートから項目を選択すると、サーバーと通信してtext_fieldを短縮名に置き換えます。問題は、これが私のカスタムバインディングの '更新'機能をもう一度起動させることです。Knockout.js - カスタムバインディングを調整する方法

Knockout.jsコード(編集:次の点に注意してくださいは、CoffeeScriptのです):

ko.bindingHandlers.ko_autocomplete = 
    init: (element, params) -> 
    $(element).autocomplete(params()) 

    update: (element, valueAccessor, allBindingsAccessor, viewModel) -> 
    unless task.name() == undefined 
     $.ajax "/tasks/name", 
     data: "name=" + task.name(), 
     success: (data,textStatus, jqXHR) -> 
      task.name(data.short_name) 


    Task = -> 
    @name = ko.observable() 
    @name_select = (event, ui) -> 
     task.name(ui.item.name) 
     false 

    task = Task.new() 

ビュー

= f.text_field :name, "data-bind" => "value: name, ko_autocomplete: { source: '/autocomplete/tasks', select: name_select }" 

カスタムバインディングにスロットルを適用する方法はありますか?

カスタムバインディングの「更新」機能が、サーバーから返されたshort_nameにtask.nameを設定したときに2回目のトリガーを停止したいだけです。

答えて

3

が、私はこのようなパターンは

ko.bindingHandlers.gsExample = 
    update: (element, valueAccessor, allBindingsAccessor, viewModel) -> 
     args = valueAccessor() 

     # Process args here, turn them into local variables 
     # eg. 
     span = args['span'] || 10 

     render = ko.computed -> 
      # Put your code in here that you want to throttle 
      # Get variables from things that change very rapidly here 

      # Note: You can access variables such as span in here (yay: Closures) 
      some_changing_value = some_observable() 

      $(element).html(some_changing_value) 

     # Now, throttle the computed section (I used 0.5 seconds here) 
     render.extend throttle : 500 

     # Cause an immediate execution of that section, also establish a dependancy so 
     # this outer code is re-executed when render is computed. 
     render() 
+2

disposeWhenNodeIsRemovedオプションを追加して新しい計算バインドを正しく処理できるようにすることが重要です。そうしないとメモリリークが発生し、パフォーマンスが低下するか悪化します。 –

2

アイソレーションに違反したくない場合は、オートコンプリートの遅延オプションとそのselectイベントを使用できるので、update関数を遠ざけることができます。

は、このようにあなたのinitを変更します(簡略化のために)更新は、それ自体を計算のいくつかの種類があるので

var options = $.extend(params(), { 
     select: function(ev, ui) { 
     var name = ui.item ? ui.item.short_name : this.value 
     task.name(name); 
     } 
    }) 
    $(element).autocomplete(options) 

あなたの更新を2回と呼ばれています。したがって、内部でアクセスされるすべての観測情報を購読します。この行のunless task.name() == undefinedには、task.name()という更新プログラムが登録されています。その後、Ajaxリクエストが成功したときにobservableをtask.name(data.short_name)に更新すると、update get notifiedとrecomputedが更新されます。

一般に
+0

ところで私のために働くために見つけた、何tran.dr_name()は何ですか? – ILya

+0

tran.dr_name()はタイプミスで、task.name()に変更されました。 – map7

+0

私はなぜあなたのアップデートが2回目に呼ばれたかの説明を追加します – ILya

関連する問題