2013-04-08 18 views
8

Knockout nie aktualizuje observables po kliknięciu przycisku resetowania formularza.typ wejścia = resetowanie i nokautowanie

http://jsfiddle.net/nQXeM/

HTML:

<form> 
    <input type="text" data-bind="value: test" /> 
    <input type="reset" value="reset" /> 
</form> 
<p data-bind="text: test"></p> 

JS:

function ViewModel() { 
    this.test = ko.observable(""); 
} 

ko.applyBindings(new ViewModel()); 

Wyraźnie wydarzenie zmiana polu tekstowym nie jest zwolniony, jak widać z tego testu jQuery: http://jsfiddle.net/LK8sM/4/

Jak czy zmusilibyśmy wszystkie obserwowalne do tworzenia danych wejściowych do aktualizacji bez konieczności ręcznego określania ich, jeśli przycisk resetowania nie uruchamia zmian?

Łatwo będzie użyć jQuery do znalezienia wszystkich danych wejściowych w formularzu i wywołać zdarzenia zmiany, ale załóżmy, że mamy tylko kontrolowaną formę nokautu.

+0

Czy jesteś przeciwny wprowadzeniu resetowania jako metody viewmodel? Jak podkreślasz, wydaje się, że jest to większy problem związany z "resetem", który nie wyzwala zmiany, co może być znaczącym problemem. – Tyrsius

+0

Jeśli metoda w viewmodelu mogłaby zresetować wszystkie obserwowalne bez konieczności ręcznego ich wyświetlania, zadziałałaby. Ale naprawdę chciałbym zresetować obserwowalne tylko do wejść. – Fergal

Odpowiedz

1

Jak wspomniano, zdarzenie change nie jest wywoływane po zresetowaniu formularza. Jeśli używasz tylko KnockOut, nie sądzę, że masz naprawdę opcje, chyba że utworzysz niestandardowe powiązania, które mogą zarejestrować się w zdarzeniu reset i wykryć zmiany - to nadal będzie wymagało ręcznego JS, ale przynajmniej będzie scentralizowane.

Bardziej ogólne podejście, choć robi wymagają jQuery, jest stworzenie funkcji, aby obsłużyć formie za reset wydarzenie, a wykrycie zmian na wejściach formularza w tym czasie.

Oto przykład programu obsługi zdarzeń, który może działać. Należy pamiętać, że nie jest to kod produkcyjny. Chciałbym spojrzeć na to z dobrej jQuery oka przed użyciem :)

$('form').on('reset', function (evt) { 
    evt.preventDefault(); 
    $(this).find('input, select, textarea').each(function() { 
     if ($(this).is('input[type="radio"], input[type="checkbox"]')) { 
      if ($(this).is(':checked') !== $(this)[0].defaultChecked) { 
       $(this).val($(this)[0].defaultChecked); 
       $(this).trigger('click'); 
       $(this).trigger('change'); 
      } 
     } else { 
      if ($(this).val() !== $(this)[0].defaultValue) { 
       $(this).val($(this)[0].defaultValue); 
       $(this).change(); 
      } 
     } 
    }); 
}); 

Oto skrzypce że demonstruje pomysł: http://jsfiddle.net/Fm8rM/2/

2

skopiowane i zmodyfikowała default Knockout submit binding w celu stworzenia podobnego wiążące dla postaci Reset wydarzenie:

ko.bindingHandlers['reset'] = { 
    init: function (element, valueAccessor, allBindings, viewModel, bindingContext) { 
     if (typeof valueAccessor() !== 'function') 
      throw new Error('The value for a reset binding must be a function'); 

     ko.utils.registerEventHandler(element, 'reset', function (event) { 
      var handlerReturnValue; 
      var value = valueAccessor(); 

      try { 
       handlerReturnValue = value.call(bindingContext['$data'], element); 
      } finally { 
       if (handlerReturnValue !== true) { 
        if (event.preventDefault) 
         event.preventDefault(); 
        else 
         event.returnValue = false; 
       } 
      } 
     }); 
    } 
}; 

można by wiązać to takiego:

<form data-bind="reset: onFormReset"> 

i onFormReset będzie na widoku modelu

function ViewModel() { 
    this.onFormReset = function() { 
     //Your custom logic to notify or reset your specific fields. 

     return true; 
    } 
} 

W swojej obsługi resetu, jeśli zwróci true, następnie JavaScript będzie nadal nazywają swoją funkcję resetowania na formularzu. Jeśli ustawiasz obserwowalne, które są związane z wartością, nie musisz JavaScript, aby zresetować formularz. W związku z tym nie można technicznie zwrócić niczego lub zwrócić wartość false w tym scenariuszu.

Ktoś inny mógłby rozszerzyć to dalej, aby automatycznie powiadomić wszystkie związane obserwacje w formularzu, ale to działało dla moich celów.