knockout.js validation textbox highlight - javascript

I'm working with validation and I am using knockout.js (and durandal.js) for a view modal.
I want to make a textbox's border red when it's blank if I click on submit button.
When a user starts to type in the textbox, the border color red should be removed.
Code is here: http://jsfiddle.net/LvHUD/1/
What I did is:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="Scripts/knockout.debug.js"></script>
<script src="Scripts/knockout.js"></script>
<script src="Scripts/knockout.validation.debug.js"></script>
<script src="Scripts/knockout.validation.js"></script>
</head>
<body>
<input type="text" data-bind='value: username' />
<br />
<button data-bind="click: submit">Submit</button>
<div data-bind="visible: showErrors, text: errors" />
<script>
function ViewModel() {
var self = this;
self.username = ko.observable().extend({
required: true
});
self.showErrors = ko.observable(false);
self.submit = function () {
self.showErrors(true);
if (self.isValid()) {
// save data here
}
}
self.errors = ko.validation.group(self);
}
ko.validation.init({
registerExtenders: true,
messagesOnModified: true,
insertMessages: false
});
ko.applyBindings(new ViewModel());
</script>
</body>
</html>

Knockout Validation adds to your observable two observables: isValid & isModified.
You can use the isValid observable to get what you are looking for.
I have modified slightly the jsfiddle provided by Bradley Trager:
http://jsfiddle.net/tBcRD/3/
Basically the data-bind attribute was changed as follows:
<input type="text" data-bind="value: username, valueUpdate: 'afterkeydown', css:{'error':(!username.isValid() && showErrors())}" />

You can use knockouts css binding to add an error class to your input box:
<input type="text" data-bind="value: username, css:{'error':showErrors}" />
Here is the jsFiddle: http://jsfiddle.net/bradleytrager/tBcRD/
Addition:
If you would like it to remove the highlight when the user types, one way of doing it is by updating your observable on the key down event, and subscribing to your observable in order to remove the error messages when the observable changes:
HTML:
<input type="text" data-bind="value: username, css:{'error':showErrors}, valueUpdate: 'afterkeydown'" />
JS:
self.username.subscribe(function () {
self.removeErrors();
});
self.removeErrors = function () {
self.showErrors(false);
};
I updated the jsFiddle with this functionality.

You can use the validationElement binding for this (wiki):
http://jsfiddle.net/tBcRD/10/
HTML:
<input type="text" data-bind="value: username, validationElement: username, valueUpdate: 'afterkeydown'" />
<br/>
<button data-bind="click: submit">Submit</button>
JS:
function ViewModel() {
var self = this;
self.username = ko.observable().extend({
required: true
});
this.validationModel = ko.validatedObservable({
username: self.username
});
self.submit = function () {
self.username.valueHasMutated();
if (this.validationModel.isValid()) {
alert("data saved");
}
}
}
ko.validation.init({
registerExtenders: true,
messagesOnModified: true,
insertMessages: false,
decorateElement: true
});
ko.applyBindings(new ViewModel());
CSS:
.validationElement {
border: 1px solid red;
}

Related

Excluding input value of reCaptcha response in a form

I am using reCaptcha v2 in a form for my contact page. After sending the form all the content was sent to email including the G-recaptcha-response. How can I exclude it using jquery in client - side.
This is the setup:
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<form method="post" name="frmcontact" id="frmcontact" action="/mail/contact">
<table width="100%" cellspacing="5">
<tr>
<td><div class="spancontacttitle">Full Name:</div>
<div class="spancontact">
<input type="text" class="contact" name="fullname" id="fullname" value="{{post.fullname}}" />
</div></td>
</tr>
<tr>
<td><div class="spancontacttitle">Email:</div>
<div class="spancontact relative">
<input type="text" class="contact" name="email_address" id="email_address" value="{{post.email_address}}" />
</div></td>
</tr>
<tr>
<td><span class="spancontacttitle">Your comments:</span>
<div class="spancontact"><textarea class="textareainquiry" name="comments" id="comments">{{post.comments}}</textarea></div></td>
</tr>
<tr>
<td>
<div class="g-recaptcha" data-sitekey="{{site['recaptcha-public-key']}}" data-callback="recaptchaCallback"></div>
<input type="hidden" class="hiddenRecaptcha required" name="hiddenRecaptcha" id="hiddenRecaptcha">
</td>
</tr>
<tr>
<td><input type="submit" class="submitinquiry" name="sbmt" id="sbmt" value="Send" /></td>
</tr>
</table>
</form>
<script type="text/javascript">
$(document).ready(function(){
function recaptchaCallback() {
$('#hiddenRecaptcha').valid();
};
$("#frmcontact").validate({
debug: true,
ignore: ".ignore",
submitHandler: function() {
document.frmcontact.submit(); return true;
},
rules: {
fullname: {
required: true
},
email_address: {
required: true,
email: true
},
hiddenRecaptcha: {
required: function () {
if(grecaptcha.getResponse() == '') {
return true;
} else {
return false;
}
}
}
},
messages: {
fullname: "This field must not be empty.",
email_address: "Please provide a valid email address.",
hiddenRecaptcha: "Error reCAPTCHA"
}
});
});
</script>
What I have tried is disabling the hidden input upon clicking and verifying the reCaptcha:
hiddenRecaptcha: {
required: function () {
if(grecaptcha.getResponse() == '') {
$('#hiddenRecaptcha').prop('disabled',false);
return true;
} else {
$('#hiddenRecaptcha').prop('disabled',true);
return false;
}
}
}
But, still, the form is sending the reCaptcha response. What I am missing here?
Your recaptcha will be useless without passing the g-recaptcha-response to the server for validation, so think about solving it on server side. But if you still want a client solution without changing your markup, here is possible way:
$(function() {
$("#frmcontact").submit(function(ev){
ev.preventDefault();
var arr = $(this).serializeArray();
//concole.log(arr);
//be sure that g-recaptcha-response is not there
var form = document.createElement("form");
form.setAttribute("method", "post");
form.setAttribute("action", "/mail/contact");
$.each(arr, function(k, v) {
var newField = document.createElement("input");
newField.setAttribute("type", "hidden");
newField.setAttribute("name", v["name"]);
newField.setAttribute("value", v["value"]);
form.appendChild(newField);
});
document.body.appendChild(form);
form.submit();
});
});
The idea is to prevent original form from submitting, then to create another form invisible for user, add all required data and submit it.
This is also described here.

Typeahead on dynamically created inputs

<input type="text" name="brand[]" class="form-control auto-brand" />
<script type="text/javascript">
$(function () {
$('input.auto-brand').each(function () {
$(this).typeahead({
name: 'brand[]',
remote: '...'
});
});
});
</script>
I would like that as I add the new inputs the typeahead is also initialized

Show error message for controls using Jquery

Script : Jquery
I am new to jquery, and I found this piece of code which I tried but didn't succeed. It uses jquery validator plugin. Here is the code :
<html>
<body>
<form id="employment-application" method="post">
<input name="full_name" type="text" />
<div id="full_name_validate"></div>
<input type="submit" />
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-form-validator/2.1.47/jquery.form-validator.min.js"></script>
<script>
$(function validate() {
var rules = {
rules: {
full_name: {
minlength: 2,
maxlength: 50,
required: true
},
},
errorPlacement: function (error, element) {
var name = $(element).attr("name");
error.appendTo($("#" + name + "_validate"));
},
};
$('#employment-application').validate(rules);
});
</script>
</body>
</html>
How do I achieve this ? here is the link http://jsfiddle.net/cMhQ7/
looks like the validator plugin version you are using is causing the issue. Try the following one http://ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js
or any from the page jqueryvalidation.org hotlink
I hope this fixes the issue.
try this
<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
<form id="employment-application" method="post">
<input name="full_name" type="text" />
<div id="full_name_validate"></div>
<input type="submit" />
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js"></script>
<script>
$(function validate() {
var rules = {
rules: {
full_name: {
minlength: 2,
maxlength: 50,
required: true
},
},
errorPlacement: function (error, element) {
var name = $(element).attr("name");
error.appendTo($("#" + name + "_validate"));
},
};
$('#employment-application').validate(rules);
});
</script>
</body>
</html>

I can't reach dynamic inputs with javascript

I want to change Cloudera Hue project code but I have some problems.
Knockout data-bind is created some html codes with foreach , when I want to reach input in this html, my code does not work correct. My app.mako file code :
.....
<div data-bind="foreach: submissionVariables" style="margin-bottom: 20px">
<div class="row-fluid">
<span data-bind="text: name" class="span3"></span>
<input type="text" data-bind="value: value,attr: { id: 'dtpicker' + name }" class="span9" />
<button class="btn fileChooserBtn" data-bind="click: $root.showTimePicker">time</button>
</div>
</div>
<input type="text" value="2014/03/15 05:06" id="datetimepickerz"/>
....
<script src="/static/js/jquery.datetimepicker.js"></script>
<script type="text/javascript">
$('#dtpickerfolder').datetimepicker()
.datetimepicker({value:'2015/04/15 05:03',step:10});
$('#dtpickereverything').datetimepicker()
.datetimepicker({value:'2015/04/15 05:03',step:10});
$('#datetimepickerz').datetimepicker()
.datetimepicker({value:'2015/04/15 05:03',step:10});
</script>
Output:
<input id="dtpickerfolder" class="span9" type="text" data-bind="value: value,attr: { id: 'dtpicker' + name }"></input>
<input id="dtpickereverything" class="span9" type="text" data-bind="value: value,attr: { id: 'dtpicker' + name }"></input>
<input id="datetimepickerz" type="text" value="2014/03/15 05:06"></input>
datetimepickerz input works correct but my dynamic inputs that ids starts with dtpicker are not working.
Can anyone help me ?
I solve this with :
self.runOrShowSubmissionModal = function runOrShowSubmissionModal() {
var script = self.currentScript();
if (! $.isEmptyObject(script.getParameters())) {
self.submissionVariables.removeAll();
$.each(script.getParameters(), function (key, value) {
self.submissionVariables.push({'name': key, 'value': value});
// CALL TO JQUERY
$("#dtpicker"+key).datetimepicker({value:"2015/04/15 05:03",step:10});
});
$("#runScriptBtn").button("reset");
$("#runScriptBtn").attr("data-loading-text", $("#runScriptBtn").text() + " ...");
$("#submitModal").modal({
keyboard: true,
show: true
});
} else {
self.runScript();
}
};
I sent my jquery in knockout function.

Multiple inputs in a Bootbox

How can I have 2 inputs instead of just one in Bootstrap's Bootbox?
I need to receive 2 values in a modal dialog.
Actually, there is a simpler way which doesn't require you to modify bootbox code.
The string you pass at the bootbox creation doesn't have to be only text: it can also be html code. That means you can include pretty much everything in the box.
To put a custom form in a bootbox, you can then create it as follow :
bootbox.confirm("<form id='infos' action=''>\
First name:<input type='text' name='first_name' /><br/>\
Last name:<input type='text' name='last_name' />\
</form>", function(result) {
if(result)
$('#infos').submit();
});
I just made function for that, check it out - here
Usage example
bootbox.form({
title: 'User details',
fields: {
name: {
label: 'Name',
value: 'John Connor',
type: 'text'
},
email: {
label: 'E-mail',
type: 'email',
value: 'johnconnor#skynet.com'
},
type: {
label: 'Type',
type: 'select',
options: [
{value: 1, text: 'Human'},
{value: 2, text: 'Robot'}
]
},
alive: {
label: 'Is alive',
type: 'checkbox',
value: true
},
loves: {
label: 'Loves',
type: 'checkbox',
value: ['bike','mom','vg'],
options: [
{value: 'bike', text: 'Motorbike'},
{value: 'mom', text: 'His mom'},
{value: 'vg', text: 'Video games'},
{value: 'kill', text: 'Killing people'}
]
},
passwd: {
label: 'Password',
type: 'password'
},
desc: {
label: 'Description',
type: 'textarea'
}
},
callback: function (values) {
console.log(values)
}
})
For me, this is the cleanest way to do it :
var form = $('<form><input name="usernameInput"/></form>');
bootbox.alert(form,function(){
var username = form.find('input[name=usernameInput]').val();
console.log(username);
});
Create hidden div with form in HTML and inject this html to bootbox message. Snippet below.
var buttonClick = function() {
var bootboxHtml = $('#js-exampleDiv').html().replace('js-exampleForm', 'js-bootboxForm');
bootbox.confirm(bootboxHtml, function(result) {
console.log($('#ex1', '.js-bootboxForm').val());
console.log($('#ex2', '.js-bootboxForm').val());
});
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.4.0/bootbox.min.js"></script>
<div id="js-exampleDiv" hidden>
<form class="js-exampleForm">
<div class="col-sm-12">
<input placeholder="Example placeholder 1" id="ex1" />
</div>
<div class="col-sm-12">
<input placeholder="Example placeholder 2" id="ex2" />
</div>
</form>
</div>
<button onclick="buttonClick();">
Open bootbox confirm dialog.
</button>
You have to write your own function which will load dialog function from bootbox.
The easiest way is to copy prompt function from source: https://raw.github.com/makeusabrew/bootbox/v3.2.0/bootbox.js
and change this part for adding new input (or whatever you need)
// let's keep a reference to the form object for later
var form = $("<form></form>");
form.append("<input autocomplete=off type=text value='" + defaultVal + "' />");
and this part for getting result:
var confirmCallback = function() {
if (typeof cb === 'function') {
return cb(form.find("input[type=text]").val());
}
};
Here is a basic example for what you need (using knockout)
<button data-bind="click: select">Button</button>
<script type="text/html" id="add-template">
<div style="display:none">
<input data-bind='value: name' placeholder="Name">
</div>
</script>
var viewModel = function () {
var self = this;
self.name = ko.observable();
self.select = function () {
var messageTemplate = $($("#add-template").html());
ko.applyBindings(self, messageTemplate.get(0));
messageTemplate.show();
bootbox.confirm({
title: "Add new",
message: messageTemplate,
callback: function (value) {
// do something
}
});
}
}
ko.applyBindings(new viewModel());
Just add as many fields and bind them in the view model
http://jsfiddle.net/6vb7e224/2/
haradwaith Has the best solution for posting form data from a bootbox. Because it works, it's simple and because he demonstrates how to Actually Submit the Form. His solution:
bootbox.confirm("<form id='infos' action=''>\
First name:<input type='text' name='first_name' /><br/>\
Last name:<input type='text' name='last_name' />\
</form>", function(result) {
if(result)
$('#infos').submit();
});
Moving the <form> tag outside of the bootbox object allows the use of PHP when posting to self and to include hidden inputs without all the clutter.
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>" id="infos">
<input type=hidden form="infos" name="created" value="<?php echo date("Y-m-d H:i:s"); ?>" />
</form>
Now you can check for $_POST['created']
<?php
if(isset($_POST['created'])){
echo "Timestamp: ".$_POST['created']; // great things happen here
}
?>
You can create the form anywhere in the body tag, it won't display because the inputs are hidden.
Hope that helps!
I know this question is pretty old now, but this is the way I've done it. I think this way is great for larger forms as putting all of the HTML in JavaScript can get ugly pretty quick.
This example uses Bootstrap but the idea is the same. Create a hidden form in HTML and then select it using JavaScript or JQuery.
HTML:
<div id="hiddenForm" class="hidden">
<form id="myForm" class="form-horizontal">
<div class="form-group">
<label class="control-label col-sm-2">First Name</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="FirstName" />
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">Last Name</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="LastName" />
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">City</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="City" />
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">State</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="State" />
</div>
</div>
</form>
</div>
JavaScript Version:
var form = document.getElementById("hiddenForm").innerHTML;
bootbox.confirm({
message: form,
callback: function (result) {
// do something
}
});
JQuery Version:
var form = $("#hiddenForm").html();
bootbox.confirm({
message: form,
callback: function (result) {
// do something
}
});
Note:
When you try to serialize the form for posting, you'll have to make sure you are actually targeting the right form. $("#myForm").serialize() will most likely not work as it will grab the actual HTML form that you built earlier. So instead, you should do something like $(".bootbox-body #myForm").serialize() to get the current form's values.

Categories