validation - Evita que la validación de knockout se evalúe en la carga inicial
knockout.js (2)
Entonces, aquí está la solución que se me ocurrió:
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());
Y aquí está el marcado ...
<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>
y aquí está el CSS
.error { color: Red; font-weight: bold; }
.help-inline { display: none; }
.error .help-inline { display: inline-block; }
.error input { border-color: Red; }
Tengo un modelo de vista simple con algunos atributos necesarios ... Quiero que cada entrada resalte en rojo si la propiedad correspondiente no es válida, pero no quiero que se muestre este resalte cuando la página se carga inicialmente ... solo cuando un valor cambia o cuando el usuario intenta guardar / continuar ...
En este momento está validando el modelo de vista en la carga inicial porque estoy especificando data-bind = "css: {error: name.isValid () == false}", pero no sé de ninguna otra manera de obtener esto para trabajar dinámicamente (similar a cómo funciona la validación jQuery no intrusiva) ...
var foo = { name: ko.observable().extend({required: true}) };
<div data-bind="css: { error: !name.isValid() }">
<input type="text" data-bind="value: name" />
</div>
Cualquier idea sobre cómo hacer que esto funcione sería apreciada ... ¡Gracias!
Un mejor enfoque es configurar la validación knockout para decorar el elemento con la clase validationElement. Esto se hace agregando esta opción de configuración:
ko.validation.configure({ decorateElement: true });
Haga clic aquí para ver un jsfiddle que demuestra esto.
**** EDITAR, EN RESPUESTA AL COMENTARIO DE LA PREGUNTA ASKER ***
Si necesita decorar el elemento principal, una solución más elegante y reutilizable es aplicar este enlace personalizado al elemento principal.
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");
}
}
};
Y aplique el enlace en su HTML así:
<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>
Eche un vistazo a este jsfiddle actualizado para verlo en acción.