2013-04-08 15 views
8

Knockout non aggiorna gli osservabili quando si fa clic su un pulsante di reimpostazione modulo.tipo di input = reset e knockout

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()); 

Chiaramente l'evento di modifica della casella di input non è di essere licenziato, come si è visto con questo test jQuery: http://jsfiddle.net/LK8sM/4/

Come andremmo a forzare tutti gli osservabili vincolati a formare gli input da aggiornare senza doverli specificare manualmente se il pulsante di reset non sta sparando degli eventi di cambiamento?

Sarebbe abbastanza facile usare jQuery per trovare tutti gli input all'interno del modulo e attivare gli eventi di cambiamento, ma si supponga di avere una forma controllata solo a eliminazione diretta.

+0

Sei contrario all'implementazione del ripristino come metodo viewmodel? Come si fa notare, questo sembra essere un problema più grande relativo al "reset's che non attiva la modifica, che potrebbe essere un problema significativo. – Tyrsius

+0

Se un metodo nel viewmodel può ripristinare tutti gli osservabili senza doverli elencare manualmente, funzionerebbe. Ma vorrei davvero resettare solo gli osservabili legati agli input. – Fergal

risposta

1

Come già menzionato, l'evento change non viene generato quando un modulo viene reimpostato. Se utilizzi solo KnockOut, non penso che tu abbia davvero opzioni a meno che non crei associazioni personalizzate che possono registrarsi per l'evento reset e rilevare le modifiche - che comporterebbero comunque il JS manuale, ma almeno sarebbe centralizzato.

Un approccio più generale, anche se fa richiedono jQuery, è quello di creare una funzione per gestire l'evento della maschera reset, e rilevare variazioni sugli ingressi del modulo in quel momento.

Ecco un esempio di gestore di eventi che potrebbe funzionare. Si prega di essere consapevoli, questo non è un codice pronto per la produzione. Vorrei guardare ad essa con un buon occhio jQuery prima di utilizzare :)

$('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(); 
      } 
     } 
    }); 
}); 

Ecco un violino che dimostra l'idea: http://jsfiddle.net/Fm8rM/2/

2

ho copiato e modificato il default Knockout submit binding al fine di creare un legame simile per la forma evento di reset:

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; 
       } 
      } 
     }); 
    } 
}; 

Faresti associa questo tipo:

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

e onFormReset sarebbe del modello di visualizzazione:

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

     return true; 
    } 
} 

nel vostro gestore di reset, se si torna vero, allora JavaScript continuerà a chiamare la sua funzione di reset sul modulo. Se stai impostando oggetti osservabili che sono destinati a valore, però, non è necessario che JavaScript continui a reimpostare il modulo. Pertanto, tecnicamente non è possibile restituire nulla o restituire false in tale scenario.

Qualcun altro potrebbe estenderlo ulteriormente per notificare automaticamente tutti gli osservabili vincolati nel modulo, ma questo ha funzionato per i miei scopi.