5

オートコンプリートを処理するカスタム バインディングがあり、ユーザーがオートコンプリートからアイテムを選択すると、サーバーと通信して text_field を短縮名に置き換えます。問題は、これにより、カスタム バインドの「更新」機能が 2 回トリガーされることです。

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 を設定したときに、カスタム バインディングの 'update' 関数が 2 回目のトリガーになるのを止めたいだけです。

4

2 に答える 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()
于 2012-05-27T00:27:09.727 に答える
2

分離に違反したくない場合は、オートコンプリートの遅延オプションを使用して、イベントを選択し、更新関数を破棄します。

次のように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()ます。次にtask.name(data.short_name)、ajaxリクエストが成功したときにオブザーバブルを更新すると、更新が通知されて再計算されます。

于 2012-05-02T01:48:07.970 に答える