2013-06-05 11 views
9

Ho un semplice modello di visualizzazione con alcuni attributi richiesti ... Voglio che ogni input evidenzi il rosso se la proprietà corrispondente non è valida, ma non voglio che questa evidenziazione visualizza quando la pagina viene inizialmente caricata ... solo quando un valore cambia o quando l'utente tenta di salvare/continuare ...Prevenire la convalida a eliminazione diretta dalla valutazione sul carico iniziale

In questo momento sta convalidando il modello di vista sul caricamento iniziale perché sto specificando il binding dei dati = "css: {error: name.isValid() == false}", ma non conosco nessun altro modo per far funzionare questo in modo dinamico (simile a come funziona validazione jQuery discreta) ...

var foo = { name: ko.observable().extend({required: true}) }; 

<div data-bind="css: { error: !name.isValid() }"> 
    <input type="text" data-bind="value: name" /> 
</div> 

Qualche idea su come realizzare questo lavoro sarebbe apprezzata ... Grazie!

risposta

2

Quindi, ecco la soluzione mi è venuta:

var Foo = function() 
{ 
    this.name = ko.observable().extend({required: true}).isModified(false); 
    this.validate: function() 
    { 
     if (!this.isValid()) 
     { 
      //... loop through all validated properties and set .isModified(true) 
      return false; 
     } 
     return true; 
    }; 
    ko.validation.group(foo); 
}; 

var Bar = function() 
{ 
    this.foo = new Foo(); 
    this.errors = ko.observableArray([]); //<-- displays errors for entire page 
    this.save = function() 
    { 
     if (!this.foo.validate()) 
     { 
      this.errors(ko.toJS(this.foo.errors())); 
     } 
    }; 
} 

ko.applyBindings(new Bar()); 

E qui è il markup ...

<div data-bind="with: foo"> 
    <div class="control-group" 
     data-bind="css: { error: name.isModified() && !name.isValid() }"> 
     <label class="control-label">Name<span class="help-inline">*</span></label> 
     <div class="controls"> 
      <input type="text" class="input-block-level" placeholder="Name" 
        data-bind="value: name, event: { blur: function() { name.isModified(true); }}" /> 
     </div> 
    </div> 

    <div class="alert alert-error" 
     data-bind="visible: $parent.errors().length > 0"> 
     <h5>Errors!</h5> 
     <ul data-bind="foreach: $parent.errors()"> 
      <li data-bind="text: $data"></li> 
     </ul> 
    </div> 
</div> 

<button type="submit" class="btn btn-primary" data-bind="click: save">Save</button> 

e qui è il CSS

.error { color: Red; font-weight: bold; } 
.help-inline { display: none; } 
.error .help-inline { display: inline-block; } 
.error input { border-color: Red; } 
5

Un approccio migliore è configurare la convalida ad eliminazione diretta per decorare l'elemento con la classe validationElement. Questo viene fatto con l'aggiunta di questa opzione di configurazione:

ko.validation.configure({ decorateElement: true }); 

Click here to see a jsfiddle demonstrating this.

**** EDIT, IN RISPOSTA ALLA DOMANDA commento da ASKER ***

Se è necessario per decorare l'elemento padre, una soluzione più elegante e riutilizzabile consiste nell'applicare questa associazione personalizzata all'elemento padre.

Javascript

ko.bindingHandlers.parentvalElement = { 
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
     var valueIsValid = valueAccessor().isValid(); 
     if(!valueIsValid && viewModel.isAnyMessageShown()) { 
      $(element).addClass("parentError"); 
     } 
     else { 
      $(element).removeClass("parentError"); 
     } 
    } 
}; 

e applicare il legame nel codice HTML in questo modo:

<form data-bind='submit:OnSubmit'> 
    <label data-bind='parentvalElement:name'> 
     <span>Name</span> 
     <input data-bind="value: name" /> 
    </label> 
    <input type='submit' value='submit' /> 
<form> 

Date un'occhiata at this updated jsfiddle to see it in action.

+0

Siamo spiacenti, nel mio sforzo di semplificare la mia esempio, ho lasciato che io sono in realtà decorare il parent-div con la classe "error", non l'elemento input stesso, in quanto vi sono altri elementi figlio/fratello che devono anche essere modificati (es. colore etichetta e "span" * visibilità), quindi questo non funzionerà per me, comunque, penso di aver trovato un modo per accom questo ... in sostanza, aggiungo .isModified (false) dopo ogni chiamata .extend(), e poi controllo se .isModified() nella mia logica di css (vedi sotto ...) –

+0

Ho aggiunto la mia risposta con un soluzione più semplice e più riutilizzabile decorare l'elemento genitore .... provalo! – RodneyTrotter

+0

Sono stato in grado di farlo funzionare senza dover creare un gestore di binding ... L'unica parte che non mi piace della mia soluzione è che sto dovendo eseguire manualmente il loop delle proprietà del modello della vista e impostare isModified (true) in modo che i campi non modificati ma non modificati mostrino il loro stato di errore quando il mio oggetto esterno chiama .save(). –

Problemi correlati