我有一个自定义绑定来处理自动完成,当用户从自动完成中选择一个项目时,我会与服务器通信并用缩短的名称替换text_field。问题是这会第二次触发我的自定义绑定的“更新”功能。
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 }"
有没有办法将油门应用于自定义绑定?
我只想在将task.name设置为从服务器发回的short_name时,再次触发自定义绑定“更新”功能。
答案 0 :(得分: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()
答案 1 :(得分: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)
您的更新是第二次调用,因为(为简化起见)更新是某种计算本身。所以它订阅了在其中访问的每个observable。在此行unless task.name() == undefined
中,您订阅了task.name()
的更新。然后,当您在ajax请求成功时使用task.name(data.short_name)
更新您的observable时,更新会收到通知并重新计算。