I have example web application with knockout.validation. I need show tooltip with message for required property - requiredText. I want create tooltip in viewmodel, not in html, but I can't?
HTML:
<!DOCTYPE html>
<html>
<head>
<title>ko.validation.test</title>
<link href="Content/bootstrap.css" rel="stylesheet" />
<link href="Content/bootstrap-theme.css" rel="stylesheet" />
</head>
<body>
<div class="container">
<h2>Required field validation</h2>
<div class="bs-docs-example">
<form>
<fieldset>
<div class="control-group" data-bind="validationElement: requiredText">
<label>Example 1 required</label>
<div class="input-append">
<input type="text" data-bind="value: requiredText" />
<button class="btn" data-bind="click: validateExample1Clicked">Validate</button>
</div>
<span class="label label-success" data-bind="visible: showExample1Success">Example 1 is valid</span>
<span class="label label-important" data-bind="visible: showExample1Failed">Example 1 is not valid</span>
<span class="help-inline" data-bind="validationMessage: requiredText"></span>
</div>
<div class="control-group" data-bind="validationElement: requiredTextUsingAttributes">
<label>Example 2 required attribute</label>
<div class="input-append">
<input type="text" data-bind="value: requiredTextUsingAttributes" required />
<button class="btn" data-bind="click: validateExample2Clicked">Validate</button>
</div>
<span class="label label-success" data-bind="visible: showExample2Success">Example 2 is valid</span>
<span class="label label-important" data-bind="visible: showExample2Failed">Example 2 is not valid</span>
<span class="help-inline" data-bind="validationMessage: requiredTextUsingAttributes"></span>
</div>
<div class="control-group">
<label>Optional</label>
<input type="text" data-bind="value: optionalText" />
</div>
<div class="form-actions">
<button class="btn btn-primary" data-bind="click: validateAllClicked">Validate all</button>
</div>
<div class="alert alert-error" data-bind="visible: showValidationErrors">
<strong>Not valid</strong> All the fields in the form are not valid.
</div>
<div class="alert alert-success" data-bind="visible: showValidationSuccess">
<strong>Valid</strong> All the fields are valid.
</div>
<div class="alert alert-info" data-bind="visible: errors().length > 0">
<strong>Form is not valid</strong> The form has following errors:
<ul data-bind="foreach: errors">
<li data-bind="text: $data"></li>
</ul>
</div>
</fieldset>
</form>
</div>
</div>
<script src="Scripts/jquery-2.1.1.js"></script>
<script src="Scripts/knockout-3.2.0.js"></script>
<script src="Scripts/knockout.validation.js"></script>
<script src="Scripts/bootstrap.js"></script>
<script src="ts/TestViewModel.js"></script>
</body>
</html>
JavaScript:
/// <reference path="../scripts/typings/knockout/knockout.d.ts" />
/// <reference path="../scripts/typings/knockout.validation/knockout.validation.d.ts" />
/// <reference path="../scripts/typings/bootstrap/bootstrap.d.ts" />
var TestViewModel = (function () {
function TestViewModel() {
var _this = this;
this.requiredText = ko.observable().extend({ required: true });
this.optionalText = ko.observable();
this.requiredTextUsingAttributes = ko.observable();
this.errors = ko.validation.group(this);
this.showValidationErrors = ko.observable(false);
this.showValidationSuccess = ko.observable(false);
this.showExample1Success = ko.observable(false);
this.showExample2Success = ko.observable(false);
this.showExample1Failed = ko.observable(false);
this.showExample2Failed = ko.observable(false);
this.validateExample1Clicked = function () {
if (!ko.validation.validateObservable(_this.requiredText)) {
alert("rrrrrr");
// Create tooltip
};
this.validateExample2Clicked = function () {
if (ko.validation.validateObservable(_this.requiredTextUsingAttributes)) {
_this.showExample2Success(true);
_this.showExample2Failed(false);
} else {
_this.showExample2Success(false);
_this.showExample2Failed(true);
}
};
this.validateAllClicked = function () {
if (_this.errors().length == 0) {
_this.showValidationSuccess(true);
_this.showValidationErrors(false);
} else {
_this.showValidationSuccess(false);
_this.showValidationErrors(true);
}
};
}
return TestViewModel;
})();
ko.validation.init({
parseInputAttributes: true,
decorateElement: true,
errorElementClass: 'error'
});
ko.applyBindings(new TestViewModel());
//# sourceMappingURL=TestViewModel.js.map
HTML:
<script src="Scripts/jquery-2.1.1.min.js"></script>
<script src="Scripts/knockout-3.2.0.js"></script>
<script src="Scripts/knockout.validation.js"></script>
<link href="Content/bootstrap.min.css" rel="stylesheet" />
<script src="Scripts/bootstrap.min.js"></script>
<script src="Scripts/ViewModel.js"></script>
<style>
body {
font-family: Helvetica, Arial, sans-serif;
padding: 10px;
}
fieldset {
padding: 10px;
border: solid 1px #ccc;
width: 500px
}
label {
display: block;
width: 100%;
padding: 5px
}
.validationMessage {
color: Red;
}
.Warning {
border-color: red;
}
.customMessage {
color: Orange;
}
input {
border:1px solid #ccc
}
</style>
<div id="contain" class="container">
<h2>Required field validation</h2>
<input data-bind="value: lastName, tooltip: isValidField" data-placement="below" data-title="Alert" data-content="We have identified this information is incorrect and must be updated." />
<button type="button" data-bind='click: submit'>Submit</button>
</div>
JavaScript:
ko.validation.rules.pattern.message = 'Invalid.';
ko.validation.configure({
//decorateInputElement: true,
decorateElement: true,
registerExtenders: true,
messagesOnModified: false,
insertMessages: false,
parseInputAttributes: true,
messageTemplate: null,
errorClass: 'Warning'
// errorAsTitle: true
});
var ViewModel = function () {
var self = this;
self.lastName = ko.observable().extend({ required: true });
self.isValidField = ko.observable();
this.submit = function () {
if (self.errors().length === 0) {
alert('Thank you.');
} else {
self.errors.showAllMessages();
self.isValidField(self.lastName.isValid());
}
};
self.errors = ko.validation.group(self);
};
ko.bindingHandlers.popover = {
init: function (element, valueAccessor, allBindingsAccessor) {
var value = valueAccessor(),
valueUnwrap = ko.unwrap(value),
allBindings = allBindingsAccessor(),
isValid = allBindings.value;
if (isValid) {
$(element).popover({
trigger: "hover"
});
} else {
$(element).popover("hide");
}
},
update: function (element, valueAccessor, allBindingsAccessor) {
var value = valueAccessor(),
valueUnwrap = ko.unwrap(value),
allBindings = allBindingsAccessor(),
isValid = allBindings.value;
if (isValid) {
$(element).popover({
trigger: "hover"
});
} else {
$(element).popover("hide");
}
}
};
ko.bindingHandlers.tooltip = {
init: function(element, valueAccessor) {
var local = ko.utils.unwrapObservable(valueAccessor()),
options = {};
ko.utils.extend(options, ko.bindingHandlers.tooltip.options);
ko.utils.extend(options, local);
$(element).tooltip(options);
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$(element).tooltip("destroy");
});
},
options: {
placement: "right",
trigger: "hover"
}
};
$(document).ready(function () {
ko.applyBindings(new ViewModel());
});
You can use extenders on observables to implement this kind of validation. Here's a sample implementation using the extender code from the Knockout documentation, just click "Run code snippet" to see a working demo:
JS & HTML:
ko.extenders.required = function(target, overrideMessage) {
//add some sub-observables to our observable
target.hasError = ko.observable();
target.validationMessage = ko.observable();
//define a function to do validation
function validate(newValue) {
target.hasError(newValue ? false : true);
target.validationMessage(newValue ? "" : overrideMessage || "This field is required");
}
//initial validation
validate(target());
//validate whenever the value changes
target.subscribe(validate);
//return the original observable
return target;
};
function TestViewModel() {
var self = this;
self.name = ko.observable('').extend({ required: "Required" });
}
ko.applyBindings(new TestViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<label for="name">Name:</label>
<p data-bind="css: { error: name.hasError }">
<input data-bind='value: name, valueUpdate: "afterkeydown"' />
<span data-bind='visible: name.hasError, text: name.validationMessage'> </span>
</p>
ko.validation has property: "insertMessages".
by defalut is true = show error in span near the element. for display error message in toolTip set value 'false' like this:
ko.validation.init{
insertMessages: false
}
Related
This is how I am using the component and sending the parameters using a Custom Element:
<div class="container" data-bind="with: DevoteeList">
<div class="row" style="padding: 10px;">
<div class="col-md-8"></div>
<div class="col-md-4">
<ko-pager params="Data: Devotees,
Modifier: $parent.DevoteeModifier,
PageCount: DevoteesPageCount(),
Url: '#Url.Action("SelectDevotees", "Devotee", new { a = 1 })'"></ko-pager>
</div>
</div>
This is how I am defining a Knockout Component. It is a Pager that I want to use at few places. But, I am receiving the error: Uncaught Error: Unable to process binding "with: function (){return SelectDevotees }"
Message: Unable to process binding "with: function (){return DevoteeList }"
Message: Unable to process binding "component: function () { return l }"
Message: Component 'ko-pager': Unknown template value: [object Object]
ko.components.register('ko-pager', {
viewModel: function (params) {
var self = this;
self.currentPage = ko.observable(1);
self.pages = ko.observableArray([]);
self.PageCount = ko.observable(params.PageCount);
//self.currentPage.subscribe(function (nv) {
// self.GetPage(self.parent);
//});
self.GetPages = function () {
for (var i = 1; i <= params.PageCount ; i++) {
self.pages.push(i);
}
return self.pages;
};
self.FirstPage = function () {
self.GetPage(1);
};
self.PrevPage = function () {
if (self.currentPage() > 1) {
var pn = self.currentPage() - 1;
self.GetPage(pn);
}
};
self.LastPage = function () {
self.GetPage(params.PageCount);
};
self.NextPage = function () {
if (self.currentPage() < params.PageCount) {
var pn = self.currentPage() + 1;
self.GetPage(pn);
}
};
self.GetPage = function (pg) {
if (pg == null)
pg = self.currentPage();
else
self.currentPage(pg);
var url = params.Url + '&pageNumber=' + pg;
$.get(url, function (data) {
var t = ko.mapping.fromJS(data);
if (params.Modifier) {
params.Modifier(t);
}
params.Data(t());
});
};
},
template: { element: document.getElementById('ko-ajax-pager') }
});
<div id="ko-ajax-pager" style="display: none;">
<div class="row" style="padding: 10px;" data-bind="visible: PageCount > 1">
<div class="col-md-1"></div>
<div class="col-md-2">
<input type="button" value="First" class="btn" data-bind="click: FirstPage" />
</div>
<div class="col-md-2">
<input type="button" value="Prev" class="btn" data-bind="click: PrevPage" />
</div>
<div class="col-md-2">
<select data-bind="options: GetPages(), value: currentPage, event: { change: GetPage(null) }">
</select>
</div>
<div class="col-md-2">
<input type="button" value="Next" class="btn" data-bind="click: NextPage" />
</div>
<div class="col-md-2">
<input type="button" value="Last" class="btn" data-bind="click: LastPage" />
</div>
<div class="col-md-1"></div>
</div>
</div>
Can someone please figure out, what is wrong?
I am trying to write a editable table using Backbone.js.
This is my Backbone.js app:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Resume builder!</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.5/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>
<style>
.jumbotron {
height: 100vh;
}
body {
background-color: white !important;
}
.table-bordered th,
.table-bordered td {
border: 1px solid #ddd!important
}
</style>
</head>
<body>
<div class="jumbotron">
<div class=container>
<h1>Resume builder</h1>
<table class="table table-bordered">
<thead>
<tr>
<th>Degree</th>
<th>Starting date</th>
<th>Ending date</th>
<th>Details</th>
</tr>
</thead>
<tbody id="informations">
<script type="text/template" id="info-row">
<tr>
<td>
<%=title%>
</td>
<td>
<%=start%>
</td>
<td>
<%=end%>
</td>
<td>
<%=details%>
</td>
<td>
<botton class="btn btn-primary" data-action="modify">edit</botton>
<botton class="btn btn-danger" data-action="delete">delete</botton>
</td>
<tr>
</script>
</tbody>
</table>
<div id="actions">
<botton class="btn btn-primary" id="addInformation">Add information</botton>
</div>
<script type="text/template" id="info-modify">
<div class="modal fade" id="edit-modal" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">INFORMATION</h4>
</div>
<div class="modal-body">
<form role="form">
<div>
<div class="radio">
<label><input type="radio" data-type="education" name="type" <%= (type == "education") ? "checked" : ""%>> Education</label>
</div>
<div class="radio">
<label><input type="radio" data-type="experience" name="type" <%= (type == "experience") ? "checked" : ""%>> Experience</label>
</div>
</div>
<div class="form-group">
<label>Title for Degree or experience (e.g. Computer Sci. | Software dev.):</label>
<input type="text" class="form-control" value="<%=title%>" name="title">
</div>
<div class="form-group">
<label>Start date:</label>
<input type="number" class="form-control" value="<%=start%>" name="start">
</div>
<div class="form-group">
<label>End date:</label>
<input type="number" class="form-control" value="<%=end%>" name="end">
</div>
<div class="form-group">
<label>Details:</label>
<textarea rows="5" class="form-control" name="details"><%=details%></textarea>
</div>
<button type="submit" class="btn btn-success">Submit</button>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</script>
</div>
</div>
<div id="modal">
</div>
</body>
<script>
$(function() {
var baseModalView = Backbone.View.extend({
el: $("#modal"),
className: 'modal fade hide',
template: _.template($("#info-modify").html()),
events: {
'hidden': 'teardown',
"click [type='submit']": "notify"
},
initialize: function() {
_.bindAll(this, "show", "teardown", "render", "notify");
this.render();
this.show();
},
show: function() {
this.$el.modal('show');
},
teardown: function() {
this.$el.data('modal', null);
this.remove();
},
render: function() {
this.$el.empty();
this.setElement(this.template(this.model.toJSON()));
},
notify: function() {
var self = this;
this.model.set({
type: self.$el.find("[type='radio']:checked").data("type"),
start: self.$el.find("[name='start']").val(),
end: self.$el.find("[name='end']").val(),
details: self.$el.find("textarea").text()
});
}
});
var InformationModel = Backbone.Model.extend({
id: -1,
defaults: {
type: " ",
title: " ",
start: 2015,
end: 2016,
details: " "
}
});
var InformationView = Backbone.View.extend({
events: {
"click [data-action='modify']": "modifyInformation",
"click [data-action='delete']": "deleteInformation"
},
template: _.template($("#info-row").html()),
initialize: function() {
_.bindAll(this, "render", "modifyInformation", "deleteInformation");
this.render();
},
render: function() {
this.setElement(this.template(this.model.toJSON()));
},
modifyInformation: function() {
var self = this;
modalView = new baseModalView({
model: self.model,
template: _.template($("#info-modify").html())
});
},
deleteInformation: function() {
this.model.destroy();
}
})
var InformationCollection = Backbone.Collection.extend({
url: "../dummy/",
model: InformationModel
});
var InformationsView = Backbone.View.extend({
el: $("#informations"),
initialize: function() {
_.bindAll(this, "render", "addInformation");
var self = this;
this.collection = new InformationCollection();
this.collection.bind("all", this.render, this);
this.collection.fetch();
// I know this is not a Backbone way...
$("#addInformation").on("click", function() {
self.addInformation();
});
},
render: function() {
this.$el.empty();
this.collection.each(function(information) {
var informationView = new InformationView({
model: information
});
this.$el.append(informationView.el);
}, this);
},
addInformation: function() {
var self = this;
modalView = new baseModalView({
model: new InformationModel()
});
}
});
new InformationsView();
$("form").submit(function(e) {
e.preventDefault();
return false;
});
});
</script>
</html>
Question:
After I edit a table row and click on submit, Backbone send a strange GET request.
The form is being submitted when you press the submit button.
This code
$("form").submit(function(e) {
e.preventDefault();
return false;
});
Won't actually stop this from happening, as when this code is executed, the form doesn't yet exist in the dom. It's only added when you create that modal view.
This is not tested, but a quick fix should be to:
$(document).on("submit", "form", function(e) {
e.preventDefault();
return false;
});
This will respond to all "submit" events on the page, and then check if they belong to a "form" element before processing the function.
Another solution, which I think is preferable as all functionality is encapsulated in your view, is to replace the submit button with a regular button in the modal template.
<button type="button" class="btn btn-success">Submit</button>
This should stop the submit event from firing, but you'll need to change the action handler the top of the baseModalView view.
If you have a form in a Backbone view, handle the form in that view, without global jQuery events.
Say you have this simple view template:
<div id="test-view">
<form id="test-form">
<input type="text" name="test">
<button type="submit">Submit</button>
</form>
</div>
Then the view only needs to catch the submit for its form:
var FormView = Backbone.View.extend({
events: {
"submit #test-form": "onSubmit"
},
onSubmit: function(e) {
e.preventDefault();
console.log("test-form submit prevented");
}
});
var view = new FormView({
el: $('#test-view')
});
I have a problem in using knockout.js validation plug in. when I try to define 'errors' in newPerson viewmodel the compiler says that newPerson is undefined. Totally, is it correct to use knockout-validation with object type of viewmodels instead of function type?
var clientModel = {
newPerson: {
EmailAddress: ko.observable().extend({
required: {
params: true,
message: "This field is required"
},
emailFormatCheck: {
params: true,
message: ""
}
}),
errors: ko.validation.group(newPerson, {
deep: true
})
}
}
ko.extenders.emailFormatCheck = function(target, overrideMessage) {
target.hasError = ko.observable();
target.validationMessage = ko.observable();
function validate(newValue) {
var matches = /^([\w-]+(?:\.[\w-]+)*)#((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i.exec(newValue);
if (matches == null) {
target.hasError(true);
target.validationMessage("The email format is wrong!!!");
} else {
target.hasError(false);
}
}
validate(target());
target.subscribe(validate);
return target;
};
ko.validation.init({
registerExtenders: true,
messagesOnModified: true,
insertMessages: true,
parseInputAttributes: true
});
ko.applyBindings();
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout-validation/2.0.3/knockout.validation.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
<div class="panel panel-primary">
<div class="panel-heading"></div>
<div class="panel-body">
<form role="form" data-bind="with: clientMode.newPerson">
<div class="form-group">
<p data-bind="css: { error: EmailAddress.hasError }">
<label>Email</label>
<br />
<input class="form-control" data-bind="value: EmailAddress, valueUpdate: 'afterkeydown'" /> <span data-bind="visible: EmailAddress.hasError, text: EmailAddress.validationMessage"> </span>
</p>
</div>
<br />
</form>
</div>
<div class="panel-footer">
<button type="submit" class="btn btn-default" data-bind=" enable:!clientModel.errors().length">Creat</button>
</div>
</div>
Thank you in advance
I'm trying to display a dialog before sending the ajax request, but I'm not getting the correct response depending of the clicked button. but I only get two results or the dialog is displayed but the request is sent or it never sends a request.
I don't want to use pure jQuery due to my strong typed view and my controller action which expects a model, so I think this will be another very big problem I'll need to resolve.
this is my layout
<!DOCTYPE html>
<html lang="es-ES">
<head>
<title>Checador</title>
<link rel="stylesheet" href="#Url.Content("~/Content/Estilos.css")">
<meta charset="utf-8">
#RenderSection("cs", required: false)
</head>
<body>
<div class="linea"> </div>
<table border="0" align="center" cellpadding="0" cellspacing="0" id="principal">
<tr>
<td id="Cuadro" align="left" valign="middle">
<span class="slogan">SOME TITLE</span><br />
<span class="subslogan">BLAH BLAH</span>
</td>
<td id="seccion" valign="top" align="right">
<div class="lineainfo">
#using ( Html.BeginForm("LogOff", "Login", FormMethod.Post, new { id = "logoutForm" }) )
{
#Html.AntiForgeryToken()
Cerrar Sesion
}
</div>
</td>
</tr>
<tr>
<td colspan="2" valign="top" id="Central">
<div>
#RenderBody()
</div>
</td>
</tr>
<tr>
<td align="right" id="Pie_Pagina" colspan="100%"><span>Abarrotes Monterrey © 2014 Mexico(Es)</span></td>
</tr>
</table>
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryui")
#RenderSection("scripts", required: false)
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
<script>
function desaparece(data, textStatus, jqXHR) {
$("#MensajeRegistro").css({ "background-color": "rgb(252, 210, 7)", "visibility": "visible", "font-size": "1.5em", "color": "#121e2d !important" });
$(".MarcoResultados").hide("slow", function () {
});
setTimeout(function () {
$("#MensajeRegistro").css("visibility", "hidden");
}, 1550);
}
$(".number").keyup(function (event) {
var valor = $(this).val();
//var valor2 = valor.charAt(0);
$(this).val(valor);
});
$(".number").keypress(function (event) {
var valor = $(this).val();
if (event.keyCode < 48 || event.keyCode > 57) {
event.preventDefault();
}
});
</script>
</body>
</html>
below is my partial view
#model checa.Models.WrapperCla
#{
ViewBag.Title = "ChecarEntradas";
}
#section cs{
<style>
#dialog-confirm {
display:none;
}
</style>
}
<div id="MensajeRegistro">
#{Html.RenderPartial("~/Views/Checador/_MensajeRegistro.cshtml",Model);}
</div>
#using ( Ajax.BeginForm("Buscar", Model.singlemp, new AjaxOptions { UpdateTargetId = "BusquedaEmpleados", HttpMethod = "Post" }) )
{
#Html.Label("Nombres")<input type="text" id="Nombres" name="Nombres" />
#Html.Label("Apellidos")<input type="text" id="Apellidos" name="Apellidos" />
#Html.Label("Clave")<input type="text" id="idd" name="idd" class="number" />
#Html.Label("Departamento")<input type="text" id="Departamento" name="Departamento" />
<input type="submit" value="Buscar" />
}
<div id="dialog-confirm" title="Empty the recycle bin?">
<p><span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>These items will be permanently deleted and cannot be recovered. Are you sure?</p>
</div>
<div id="BusquedaEmpleados" class="ResultadosEmpleados">
#{Html.RenderPartial("~/Views/Checador/_EmpleadosEncontrados.cshtml",Model.Empleados);}
</div>
#section Scripts
{
<script type="text/javascript">
function Confirmacion() {
var response = false;
$("#dialog-confirm").dialog({
resizable: false,
height: 140,
modal: true,
buttons: {
"Cofirmar": function () {
noenvio(response);
$(this).dialog("close");
},
"Cancelar": function () {
response = false;
$(this).dialog("close");
}
}
});
return response;
}
function noenvio(response) {
response = false;
return response;
}
</script>
}
this one is another partial view which displays the query results of the partial view
#model checa.Models.WrapperCla
<div class="MarcoResultados">
#foreach ( var epm in Model.Empleadoslist )
{
using ( #Ajax.BeginForm("Checar", epm, new AjaxOptions { UpdateTargetId = "MensajeRegistro", HttpMethod = "Post", OnSuccess = "desaparece(data, status, xhr)", OnBegin = "return Confirmacion()" },
new { Class = "empleadoForm" }) )
{
<div class="empleado">
#{
String convertido = "";
if ( epm.Foto != null )
{
convertido = System.Convert.ToBase64String(epm.Foto);
}
<img class="fempleado" src="data:image;base64,#convertido" width="80" height="80" />
}
<label>Empleado:#epm.nombres #epm.apellidos</label>
<label>Numero Empleado:#epm.idd</label>
<label>Departamento:#epm.Departamento</label>
<input type="submit" value="Checar" />
</div>
}
}
</div>
I'd like to use Knockout.js to highlight errors on a form.
Currently i see all errors when i get the form,
I want to get them only if the user press on Save button.
So I'm try to set a flag that will be true only if the user press on it, and then to use it in all form but i don't have success with that.
I will apreciate some help with that. (or any other way to do it)
so i will need someting like that on my html:
<div class='liveExample' data-bind="css: {hideErrors: !hasBeenSubmittedOnce()">
and somewhere in my js file:
this.hasBeenSubmittedOnce = ko.observable(false);
this.save = function(){
this.hasBeenSubmittedOnce(true);
}
that my files
HTML
<div class='liveExample' data-bind="css: {hideErrors: !hasBeenSubmittedOnce()">
<form class="form-horizontal" role="form">
<div class="form-group">
<label class="col-sm-3 control-label">Store:</label>
<div class="col-sm-3" data-bind="css: { error: storeName.hasError() }">
<input data-bind='value: storeName, valueUpdate: "afterkeydown"' />
<span data-bind='text: storeName.validationMessage'> </span>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Company ID:</label>
<div class="col-sm-3" data-bind="css: { error: companyId.hasError }">
<input data-bind='value: companyId, valueUpdate: "afterkeydown"' />
<span data-bind='text: companyId.validationMessage'> </span>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Address</label>
<div class="col-sm-3" data-bind="css: { error: address.hasError }">
<input data-bind='value: address, valueUpdate: "afterkeydown"' />
<span data-bind='text: address.validationMessage'> </span>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Phone:</label>
<div class="col-sm-3" data-bind="css: { error: phone.hasError }">
<input data-bind='value: phone, valueUpdate: "afterkeydown"' />
<span data-bind='text: phone.validationMessage'> </span>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-4">
<button class="btn btn-primary" data-bind="click: save">Add store</button>
</div>
</div>
</form>
Store:
Company ID:
Address
Phone:
Add store
</form>
js
define(['knockout'], function (ko){
ko.extenders.required = function(target, overrideMessage) {
//add some sub-observables to our observable
target.hasError = ko.observable();
target.validationMessage = ko.observable();
//define a function to do validation
function validate(newValue) {
target.hasError(newValue ? false : true);
target.validationMessage(newValue ? "" : overrideMessage || "This field is required");
}
validate(target());
target.subscribe(validate);
return target;
};
function AppViewModel(storeName, companyId, address, phone) {
this.storeName = ko.observable(storeName).extend({ required:"" });
this.companyId = ko.observable(companyId).extend({ required: "" });
this.address = ko.observable(address).extend({ required: "" });
this.phone = ko.observable(phone).extend({ required: ""});
this.hasError = ko.computed(function(){
return this.storeName.hasError() || this.companyId.hasError();
}, this);
this.hasBeenSubmittedOnce = ko.observable(false);
this.save = function(){
this.hasBeenSubmittedOnce(true);
}
}
return AppViewModel;
});
CSS file
.form-group span {
display: inherit;
}
.hideErrors .error span {
display: none;
}
I did some work around for this and not sure it is better way or not.
var showError=ko.observableArray([]);//it will store show Error Message
ko.extenders.required = function(target, overrideMessage) {
//add some sub-observables to our observable
target.hasError = ko.observable();
target.validationMessage = ko.observable();
//define a function to do validation
function validate(newValue) {
target.hasError($.trim(newValue) ? false : true);
target.validationMessage($.trim(newValue) ? "" : overrideMessage || "This field is required");
}
showError.push(function(){validate(target());});
target.subscribe(validate);
return target;
};
function AppViewModel(storeName, companyId, address, phone) {
this.storeName = ko.observable(storeName).extend({ required:"" });
this.companyId = ko.observable(companyId).extend({ required: "xcxcx" });
this.address = ko.observable(address).extend({ required: "" });
this.phone = ko.observable(phone).extend({ required: ""});
this.hasError = ko.computed(function(){
return self.storeName.hasError() || self.companyId.hasError();
}, this);
this.hasBeenSubmittedOnce = ko.observable(false);
this.save = function(){
ko.utils.arrayForEach(showError(),function(func){
func();
});
}
}
ko.applyBindings(new AppViewModel());
Fiddle Demo
You can use the visible knockout binding:
<div data-bind="visible: hasBeenSubmittedOnce">
As for the error class, you can use the define the default knockout validation class: 'validationElement' and call
ko.validation.init({ decorateElement: true});
Here you can find more:
https://github.com/Knockout-Contrib/Knockout-Validation/wiki/Configuration
(please note that decorateElement has been renamed 2013-11-21 to 'decorateInputElement')