2012-05-02 4 views
5

Mam niestandardowe powiązanie do obsługi autouzupełniania, a gdy użytkownik wybierze element z autouzupełniania, mówię do serwera i zastępuję pole tekstowe skróconą nazwą. Problem polega na tym, że po raz drugi uruchamia funkcję "aktualizacji" mojego niestandardowego powiązania.Knockout.js - w jaki sposób przepustnicy niestandardowe wiązania

kod

Knockout.js (edit: Uwaga Poniżej znajduje 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() 

View

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

Czy istnieje sposób, aby zastosować przepustnicę do zwyczaju wiążąca?

Po prostu chcę zatrzymać funkcję "aktualizacji" niestandardowych wiązań, po raz drugi, gdy ustawię nazwę zadania na krótką nazwę wysłaną z serwera.

Odpowiedz

3

Ogólnie Znalazłem wzór tak, aby pracować dla mnie

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

. Ważne jest, aby dodać opcję disposeWhenNodeIsRemoved, aby umożliwić prawidłowe ułożenie nowego obliczonego powiązania, w przeciwnym razie wystąpią wycieki pamięci i pogorszenie wydajności lub pogorszenie. –

2

Jeśli nie chcesz naruszać izolacji, możesz skorzystać z opcji opóźnienia autouzupełniania i wybranego zdarzenia, odrzucając funkcję aktualizacji.

Modyfikowanie init, w ten sposób:

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

Twoja zmiana nazywa się po raz drugi, ponieważ (dla uproszczenia) Aktualizacja jest jakaś komputerowa sama. Więc subskrybuje każdy obserwowalny dostęp w nim. W tej linii unless task.name() == undefined subskrybujesz aktualizację do task.name(). Następnie, gdy zaktualizujesz swoje obserwowalne z task.name(data.short_name) po powodzeniu żądania ajax, aktualizacja otrzyma powiadomienie i ponownie obliczona.

+0

btw, co tran.dr_name() jest? – ILya

+0

tran.dr_name() było literówką, zmieniono na task.name(). – map7

+0

Dodałem więc wyjaśnienie, dlaczego twoja aktualizacja została wywołana po raz drugi. – ILya