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>
Related
I have the following program with a submit form and a javascript part, which should reset my textboxes, but after submitting nothing happens.
<div class="row">
<div class="col-md-4">
#using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
<table>
<tr>
<td>#Html.Label("Name")</td>
<td>#Html.TextBox("name", null, new { id = "tb1" })</td>
</tr>
<tr>
<td>#Html.Label("Mail")</td>
<td>#Html.TextBox("mail", null, new { id = "tb2" })</td>
</tr>
</table>
<input type="submit" value="Send" onclick="clear" />
}
</div>
</div>
#section scripts {
<script type="text/javascript">
$(document).ready(function () {
});
function clear() {
$("#tb1").val("");
$("#tb2").val("");
}
</script>
}
Is there anything I´m missing? Any help is appreciated!
**** Edit - Apparently this only happens on MS Edge. It works with a single Enter on Chrome and Firefox.**
I have a problem where a form is only submitted after I hit enter twice on a text box.
The form is extremely simple, just 1 text box and the submit button.
It all works fine if I explicitly hit the Submit button; data displays correctly and all, but I want to also submit by hitting enter. And I noticed that if i just hit enter once, it does not work. It isn't until I hit enter twice that the form actually submits.
I already tried binding to jquery's keypress, and even doing .live(), but even then it only works after hitting enter twice.
In case it's relevant, the reason I'm binding to DOMSubtreeModified on Search.cshtml is because I'm using the datatables.net jQuery plugin, and I could not find a way to call the .DataTable() method on the table after the form submits, so I had to call it after the HTML on the div changes.
My setup is as follows:
Search.cshtml
<div id="search-form">
#Html.Action("SearchForm", "Item")
</div>
<br />
<br />
<div id="search-results">
</div>
#section scripts {
<script type="text/javascript">
$('#search-results').bind("DOMSubtreeModified", function () {
$('#items').DataTable();
});
</script>
}
_SearchFormPartial.cshtml
#using (Ajax.BeginForm("Search", "Item", FormMethod.Post,
new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
UpdateTargetId = "search-results"
}))
{
<div class="row">
<div class="col-md-3">
<input type="text" id="term" name="term" placeholder="Search by Item Name" class="form-control" autofocus />
</div>
<div class="col-md-2">
<input type="submit" value="Search" id="btnSearch" class="btn btn-default" />
</div>
</div>
}
_SearchResultsPartial.cshtml
#model List<MyItem>
#{
ViewBag.Title = "Search Results";
}
<table class="table table-striped" id="items">
<thead>
<tr>
<td><strong>Name</strong></td>
<td><strong>Type</strong></td>
<td><strong>Status</strong></td>
</tr>
</thead>
#foreach (var item in Model)
{
<tr class="clickable-row">
<td>#item.Name</td>
<td>#item.Type</td>
<td>#item.Status</td>
</tr>
}
</table>
#section scripts {
<script type="text/javascript">
$(document).ready(function () {
$("#items tr").css('cursor', 'pointer');
});
$("#items tr.clickable-row").on('click', function (e, row, $element) {
var url = $(this).closest('tr').children('td.secretLink').children(":first").attr("href");
window.location = url;
});
</script>
}
This worked in Chrome and in IE edge when I clicked Enter once, for both browsers
https://dotnetfiddle.net/DUvLqb
Controller/ViewModel
namespace Testy20161006.Controllers
{
public class MyItem
{
public string Name { get; set; }
public string Type { get; set; }
public string Status { get; set; }
}
public class HomeController : Controller
{
public ActionResult SearchForm()
{
return View();
}
public ActionResult SearchMe(string term)
{
return View();
}
public ActionResult Search()
{
var myItem1 = new MyItem { Name = "Name1", Status = "Stat1", Type = "Type1" };
var myItem2 = new MyItem { Name = "Name2", Status = "Stat2", Type = "Type2" };
var myItem3 = new MyItem { Name = "Name3", Status = "Stat3", Type = "Type3" };
IList<MyItem> list = new List<MyItem>();
list.Add(myItem1);
list.Add(myItem2);
list.Add(myItem3);
return View(list);
}
Search.cshtml
#model List<Testy20161006.Controllers.MyItem>
#{
ViewBag.Title = "Search";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Search</h2>
<div id="search-form">
#*changing this action*#
#*#Html.Action("SearchForm", "Item")*#
#Html.ActionLink("Click to Search", "SearchForm")
</div>
<br />
<br />
<div id="search-results">
</div>
#Html.Partial("~/Views/Home/_SearchFormPartial.cshtml")
#Html.Partial("~/Views/Home/_SearchResultsPartial.cshtml", Model)
#section scripts {
<script type="text/javascript">
$('#search-results').bind("DOMSubtreeModified", function () {
$('#items').DataTable();
});
</script>
}
_SearchFormPartial.cshtml
#*Changing Ajax.BeginForm Signature*#
#*#using (Ajax.BeginForm("Search", "Item", FormMethod.Post,
new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
UpdateTargetId = "search-results"
}))
{*#
#using (Ajax.BeginForm("SearchMe", "Home", FormMethod.Post,
new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
UpdateTargetId = "search-results"
}))
{
<div class="row">
<div class="col-md-3">
<input type="text" id="term" name="term" placeholder="Search by Item Name" class="form-control" autofocus />
</div>
<div class="col-md-2">
<input type="submit" value="Search" id="btnSearch" class="btn btn-default" />
</div>
</div>
}
_SearchResultsPartial
#model List<Testy20161006.Controllers.MyItem>
#{
ViewBag.Title = "Search Results";
}
<table class="table table-striped" id="items">
<thead>
<tr>
<td><strong>Name</strong></td>
<td><strong>Type</strong></td>
<td><strong>Status</strong></td>
</tr>
</thead>
#foreach (var item in Model)
{
<tr class="clickable-row">
<td>#item.Name</td>
<td>#item.Type</td>
<td>#item.Status</td>
</tr>
}
</table>
#section scripts {
<script type="text/javascript">
$(document).ready(function () {
$("#items tr").css('cursor', 'pointer');
});
$("#items tr.clickable-row").on('click', function (e, row, $element) {
var url = $(this).closest('tr').children('td.secretLink').children(":first").attr("href");
window.location = url;
});
</script>
}
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 want to prevent adding an email address which already exists.
I want to disable adding more than 5 email addresses and names.
This is controller.js:
var helloApp = angular.module("helloApp", []);
helloApp.controller("CompanyCtrl", function($scope) {
$scope.companies = [
{ 'name':'Infosys Technologies',
'email': 'firstdawn1994#gmail.com',},
{ 'name':'Cognizant Technologies',
'email': 'cognizant#gmail.com',},
{ 'name':'Wipro',
'email': 'wipro#gmail.com',},
{ 'name':'Tata Consultancy Services (TCS)',
'email': 'tata#gmail.com',},
{ 'name':'HCL Technologies',
'email': 'hcl#gmail.com',},
];
$scope.addRow = function(){
$scope.companies.push({ 'name':$scope.name, 'email': $scope.email });
$scope.name='';
$scope.email='';
};
$scope.removeRow = function(name){
var index = -1;
var comArr = eval( $scope.companies );
for( var i = 0; i < comArr.length; i++ ) {
if( comArr[i].name === name ) {
index = i;
break;
}
}
if( index === -1 ) {
alert( "Something gone wrong" );
}
$scope.companies.splice( index, 1 );
};
});
This is the HTML:
<html ng-app="helloApp">
<head>
<title>Hello AngularJS - Add Table Row Dynamically</title>
<link rel="stylesheet"
href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<script
src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script
src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script
src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.17/angular.min.js"></script>
<script src="js/controllers.js"></script>
</head>
<!-- Controller name goes here -->
<body ng-controller="CompanyCtrl">
<input type="submit" value="Add New User +" class="btn btn-primary" id="add_user" />
<form class="form-horizontal" role="form" ng-submit="addRow()" id="submit_form">
<div class="form-group">
<label class="col-md-2 control-label">Name</label>
<div class="col-md-4">
<input type="text" class="form-control" name="name"
ng-model="name" />
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">Email</label>
<div class="col-md-4">
<input type="text" class="form-control" name="email"
ng-model="email" />
</div>
</div>
<div class="form-group">
<div style="padding-left:110px">
<input type="submit" value="Submit" class="btn btn-primary"/>
</div>
</div>
</form>
<table class="table">
<tr>
<th>Name
</th>
<th>Email
</th>
</tr>
<tr ng-repeat="company in companies | limitTo : 5">
<td>{{company.name}}
</td>
<td>{{company.email}}
</td>
<td>
<input type="button" value="Remove" class="btn btn-primary" ng-click="removeRow(company.name)"/>
</td>
</tr>
</table>
<script type="text/javascript">
$(document).ready(function() {
$('#submit_form').hide();
$('#add_user').click(function(event) {
$('#submit_form').toggle(1000);
});
});
</script>
</body>
</html>
To achieve this please modify your addRow function to this code below
$scope.addRow = function(){
//store the new company in a variable for easy reference
var newCompany = { 'name':$scope.name, 'email': $scope.email };
//loops through existing companies to check if the email exists already
var emailExists = $scope.companies.some(function(item){
return item.email === newCompany.email;
});
//validation check before inserting the new company.
if( $scope.companies.length < 5 && !emailExists){
$scope.companies.push(newCompany);
$scope.name='';
$scope.email='';
}else{
//display some validation messages
}
};
Also in your HTML, you can disable the Add button so that the user does not have the opportunity to add more Companies if you already have up to 5 companies by adding the attribute below the button to:
data-ng-disable="companies.length > 5"
Hence, the button becomes:
<input type="submit" data-ng-disable="companies.length > 5" value="Submit" class="btn btn-primary"/>
Hope this helps
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
}