Validate dynamically generated form with jQuery Validator - javascript

Sorry for keep asking this, but I just can't figure it out. I've reduced the question to just the bare minimum.
How can I validate a dynamically generated form? Below is my attempt, but as seen, it shows up as passing validation.
https://jsfiddle.net/j2pgobze/1/
<form id="myForm">
<input type="text" name="email" id="email" value="bademail" >
</form>
<button id="validate">validate</button>
var myValidateObj = {
rules: {
email: {
email: true
}
}
};
$(function () {
jQuery.validator.setDefaults({
debug: true,
success: "valid"
});
$('#validate').click(function () {
//Validate the traditional form
var validate1 = $('#myForm').validate(myValidateObj);
console.log('Option 1', $('#myForm'), $('#email'), $('#email').val(), validate1.element('#email'), $('#email').valid(), $('#myForm').valid());
//Validate dynamically created form
var input = $('<input />', {
type: 'text',
name: 'email',
value: 'bademail'
});
//input.prop('value', 'bademail');
var form = $('<form />').append(input);
var validate = form.validate(myValidateObj);
console.log('Option 2', form, input, $('#email').val(), validate.element(input), input.valid(), form.valid());
});
});

The button needs to be inside the form and be a type="submit" in order for the plugin to capture the click.
Do not put .validate() within a click handler (See item 1). It's only used to initialize the plugin on a form. Exception, below we are creating the new form within a click handler and then immediately calling .validate() on the new form.
With these two small changes, the validation on the static form is working: jsfiddle.net/j2pgobze/3/
I rewrote your DOM manipulation code for clarity. I simply duplicated the HTML for the form and gave it a new ID: http://jsfiddle.net/zem84tfp/
$(function () {
// INITIALIZE plugin on the traditional form
var validate1 = $('#myForm').validate(myValidateObj);
$('#newform').one('click', function () {
// code here to create new form; give it new ID
// do not duplicate ID on anything else
// INITIALIZE plugin on the new form
var validate = $('#myForm2').validate(myValidateObj);
});
});

Related

jQuery form: on submit validation issue + stay on the same page after submit

I'm not a programmer, just trying to fix & improve my contact form. Right now it's a HTML form (name, email, 4 checkboxes as subject, message). And mail.php (update: method="POST"). Everything works, I receive all form data.
But I have found a script to validate name, email & message inputs, here it is:
<script>
$(document).ready(function() {
<!-- Real-time Validation -->
<!--Name can't be blank-->
$('#contact_name').on('input', function() {
var input=$(this);
var is_name=input.val();
if(is_name){input.removeClass("invalid").addClass("valid");}
else{input.removeClass("valid").addClass("invalid");}
});
<!--Email must be an email -->
$('#contact_email').on('input', function() {
var input=$(this);
var re = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
var is_email=re.test(input.val());
if(is_email){input.removeClass("invalid").addClass("valid");}
else{input.removeClass("valid").addClass("invalid");}
});
<!--Message can't be blank -->
$('#contact_message').keyup(function(event) {
var input=$(this);
var message=$(this).val();
console.log(message);
if(message){input.removeClass("invalid").addClass("valid");}
else{input.removeClass("valid").addClass("invalid");}
});
<!-- After Form Submitted Validation-->
$("#button").click(function(event){
var form_data=$(".myform").serializeArray();
var error_free=true;
for (var input in form_data){
var element=$("#contact_"+form_data[input]['name']);
var valid=element.hasClass("valid");
var error_element=$("span", element.parent());
if (!valid){error_element.removeClass("error").addClass("error_show"); error_free=false;}
else{error_element.removeClass("error_show").addClass("error");}
}
if (!error_free){
event.preventDefault();
}
else{
alert('No errors: Form will be submitted');
}
});
});
</script>
Originally, it was showing error messages next to input fields, I decided not to use them (spans in HTML, "error" & "errow_show" classes in CSS), leaving just input field highlighting ("valid" green/"invalid" red CSS classes).
I feel like the problem is these lines:
var error_element=$("span", element.parent());
if (!valid){error_element.removeClass("error").addClass("error_show"); error_free=false;}
else{error_element.removeClass("error_show").addClass("error");}
And this script highlights empty name, invalid email and empty message. But when I click "SEND" button, the script, despite highlighting invalid fields, shows the alert "No errors. Form will be sumbitted" and sends form to me. The problem seems to be in its last part. I do not know how to properly remove "span", "error" and "error_show" from this script (3 lines before the second IF). I want my form to send everything to me if everything is valid and not send anything ("disabled button"?) if something is invalid. Without any alerts. If it also could stay on the same page after sumbitting... it would be an ideal thing (Submit form and stay on same page?, Submit a form using jQuery, jQuery AJAX submit form). Any help would be greatly appreciated!:)
UPDATE: form html: (removed as unnecessary now)
UPDATE 2: well, guys, this (weird? incorrect? semi-correct?) code I suddenly made up checks and highlights correctly as "valid"/"invalid" all 3 required fields (name, email, message) and shows correct alerts (I'll remove them later) on #button_send click and even sends the whole form with non-required non-validated checkboxes to me:
$('#button_send').click(function(){
if ($('#contact_name').hasClass('valid') && $('#contact_email').hasClass('valid') && $('#contact_message').hasClass('valid')) {
alert('No errors');
$('.form').submit();
} else {
alert('Errors');
return false;
}
});
I want to thank everyone for every piece of advice and help.
You want to prevent the default action of the button and then call submit when you are ready.
http://api.jquery.com/event.preventDefault/
<!-- After Form Submitted Validation-->
$("#button").click(function(event){
// prevent the form from being submitted
event.preventDefault();
var form_data=$(".myform").serializeArray();
var error_free=true;
for (var input in form_data){
var element=$("#contact_"+form_data[input]['name']);
var valid=element.hasClass("valid");
var error_element=$("span", element.parent());
if (!valid){error_element.removeClass("error").addClass("error_show"); error_free=false;}
else{error_element.removeClass("error_show").addClass("error");}
}
if (error_free) {
alert('No errors: Form will be submitted');
// submit the form if no errors
$( ".myform" ).submit();
}
else{
alert('Errors shown');
}
});
});
The Problem:
The behavior you're seeing is because you deleted the controls that your code was using to validate/invalidate your form. Without those controls, due to the way it was written, it defaults to a valid state regardless of the actual validity of the inputs.
Solution #1:
If you have a backup, the easy thing to do would be to revert back to how it was before you touched it and just add 'hidden' as properties to your spans. This way they wouldn't be visible to your user, but would still validate the inputs for you.
Solution #2:
If you aren't able to do that, then you'll need to modify your submission code to validate off the remaining controls and their classes. I don't have your full code to test this, but I believe something like this would work:
<!-- After Form Submitted Validation-->
$("#button").click(function(event){
var error_free=false;
$.each($('.myform > input'), function() {
error_free = $(this).hasClass('valid');
if (!error_free){
event.preventDefault();
return false;
}
});
if (error_free){
alert('No errors: Form will be submitted');
}
});
The snippet above loops over any inputs inside of the control with the class 'myform' and checks if they have the 'valid' class, then sets a variable true or false depending. If it detects there is an invalid control, it exits the loop and does not proceed with Posting the form.
Hope that helps.
If you want it to be save, I recommend you to do backend validation to.
If in your HTML form, the method is set to "post", this will do the magic;
$(document).ready(function() {
<!-- Real-time Validation -->
<!--Name cant be blank-->
$("#contact_name").on('input', function() {
var input=$(this);
var is_name=input.val();
if(is_name){input.removeClass("invalid").addClass("valid");}
else{input.removeClass("valid").addClass("invalid");}
});
<!--Email must be an email -->
$("#contact_email").on('input', function() {
var input=$(this);
var re = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
var is_email=re.test(input.val());
if(is_email){input.removeClass("invalid").addClass("valid");}
else{input.removeClass("valid").addClass("invalid");}
});
<!--Message cant be blank -->
$("#contact_message").keyup(function(event) {
var input=$(this);
var message=$(this).val();
console.log(message);
if(message){input.removeClass("invalid").addClass("valid");}
else{input.removeClass("valid").addClass("invalid");}
});
<!-- After Form Submitted Validation-->
$("#button").click(function(event){
event.preventDefault();
var form_data=$(".myform").serializeArray();
var error_free=true;
for (var input in form_data){
var element = $("#contact_"+form_data[input]['name']);
var valid = element.hasClass("valid");
if (!valid){
error_free=false;
element.addClass("invalid");
}
}
if (error_free){
//Submit the form
$.post({url: 'mail.php', data: form_data, dataType: 'json'}).done(function(){
//clear the fields
$("[id^=contact_]").val('');
})
}
});
});

Codeigniter Javascript dynamic inputs only submitting first item

I am trying to submit a form with dynamic inputs. I am able to add a several inputs via the javascript. However, when I submit, it only picks up the first added input value. I hope someone can take a look at this for me as I've tried to fix this for so long. Thank you
Controller
public function update(){
$this->form_validation->set_rules('first_name', 'Firstname', 'trim|required|xss_clean');
$this->form_validation->set_rules('last_name', 'Lastname', 'trim|required|xss_clean');
$this->form_validation->set_rules('phone_number', 'Phone', 'trim|required|xss_clean');
$this->form_validation->set_rules('date_of_birth', 'Date of Birth', 'trim|required|xss_clean');
$this->form_validation->set_rules('address', 'Address', 'trim|required|xss_clean');
$this->form_validation->set_rules('country', 'Country', 'trim|required|xss_clean');
$this->form_validation->set_rules('active', 'Is Active', 'trim|required|xss_clean');
$id = $this->input->post('id');
$person_id = $this->input->post('person_id');
$first_name = $this->input->post('first_name');
$last_name = $this->input->post('last_name');
$date_of_birth = $this->input->post('date_of_birth');
$phone_number = $this->input->post('phone_number');
$account_number = $this->input->post('account_number');
$address = $this->input->post('address');
$country = $this->input->post('country');
$active = $this->input->post('active');
if($this->form_validation->run()==false){
$this->edit();
}else{
$person = array(
'first_name'=>$first_name,
'last_name'=>$last_name,
'date_of_birth'=>$date_of_birth,
'phone_number'=>$phone_number,
'address'=>$address,
'country'=>$country,
);
$account = array(
'is_active'=>$active
);
print_r($account_number);
}
}
View
<script>
$(document).ready(function(){
var max_fields = 5;
var wrapper = $("#new_account_number_container");
var addInput = $("#addInput");
var i;
$(addInput).click(function(e){
i = $("#new_account_number_container input").length;
e.preventDefault();
if(i<max_fields){
i++;
$(wrapper).append('<div><input type="text" name="account_number[]" class="form-control" placeholder="Account Number" required autofocus>Remove<div>');
}
});
$(wrapper).on("click",".remove", function(e){ //user click on remove text
e.preventDefault(); $(this).parent('div').remove();
i--;
});
});
</script>
<div id="new_account_number_container" class="form-group col-sm-8">
<input type="text" name="account_number[]" class="form-control" placeholder="Account Number" autofocus>
<br>
</div>
<div class="form-group col-sm-8">
<button class="pull-right btn btn-primary" id="addInput">Add</button>
</div>
First thing, I can not see <form> in your code. Without this tag, you can not get desired behaviour:
After that,
To give you formatted code snippet I am posting that suggestion as an answer:
// this is the id of the form
$("#form_id").submit(function(e) {
var url = "path/to/your/script.php"; // the script where you handle the form input.
$.ajax({
type: "POST",
url: url,
data: $("#form_id").serialize(), // serializes the form's elements.
success: function(data)
{
alert(data); // show response from the php script.
}
});
e.preventDefault(); // avoid to execute the actual submit of the form.
});
We need to remember that, PHP serves as back-end application. So anything dynamic (like DOM input text in your case) may NOT be submitted simply because the <form> tag is not updated that you have new text-box input.
One of the thing you could do is to use ajax for form submitting. Because it is Client-Side Script, it could detect all DOM input text box on your page, and serialized it before send the request to the back-end.
First by adding a <form> tag between your input and button component. Example like <form id="frm" name="frm">.
Second, by adding a button which trigger a JavaScript function.
function update(){
if(confirm("Are you sure?")==true){
$.post(
"*absolute_project_root_path*/*controller*/update",
$('#frm').serialize(),
function(response){
//what to do with your response..
}
);
}
return false;
}
Then you can access the submitted form in the back-end like usual.

Knockout.js validation on hidden fields

I am implementing knockout validation for my form, and I want to make a field required only if it is showing. Depending on the selection of other fields in the form, some controls may be hidden by visibility:hidden or display:none. How can I make these fields required only if shown? I have tried this
var name = ko.observable().extend({
required: {
onlyIf: function () {
return ($('#name').is(':visible'));
},
message: '*** Required'
}
});
But it doesn't seem to work, and I'm not sure if it should (can you write custom logic like that in knockout onlyIf params?).
Thanks for any help.
As mentioned in comments all you need to do is
Declare a observable in ViewModel per say self.nameVisible=ko.observbale() set the value it True/False from anywhere (either from DB or based on other control selection) . Later on you should use the self.nameVisible() in your validations i.e with .extend & onlyIf combo to make things(hide/show element+dynamic conditional validation) work .
Html:
<input type="text" data-bind="value:name,visible:nameVisible"/>
viewModel:
var ViewModel = function () {
var self = this;
self.nameVisible = ko.observable(true); //Set it dynamically
self.name = ko.observable().extend({
required: {
message: '*** Required',
onlyIf: self.nameVisible
}
});
};
ko.applyBindings(new viewModel());

jQuery Calculator - validation executes instead of calculator

I made a jQuery calculator that takes Fuel amount and Burn rate to give Time til empty to display on my screen. I also am using form validation.
When I click on the calculator button it runs form validation for some and tries to run the server-side code which is fine if I was clicking on the form submit button (and that button performs the way it should). But I have my calculator button "id" attribute and "name" attribute different than the form submit button. So I don't understand why when I click on the calculator button it tries to run form validation. In addition, it doesn't give me the total in the
$('#time-empty-field').val(time_empty);
field. Ideally, I want the calculator to show the total in the $('time-empty-field') and not run form validation.
I know my HTML is fine and from what I can see I don't see anything wrong with my jQuery. Maybe a different set of eyes can help on this. Any help would be much appreciated. Thanks!
$(function() {
$('#id').focus();
// To clear phone example when active
$('#phone').focus(function() {
var field = $(this);
if (field.val() == field.prop('defaultValue')) {
field.val('').css('color', 'black');
}
});
// Reveals System Report
$('#system-box input').click(function() {
if ($(this).attr('checked')) {
$('#system-report').slideDown('fast');
} else {
$('#system-report').slideUp('fast');
}
});
//Calculator
$('#calculator-submit-btn').submit(function() {
var fuel_amount = $('#fuel-amount-field').val();
var burn_rate = $('#burn-rate-field').val();
var time_empty = fuel_amount * burn_rate;
time_empty = time_empty.toFixed(2);
$('#time-empty-field').val(time_empty);
});
// Form validation plug-In
$('#form1').validate({
rules: {
id: {
required: true,
number: true
},
password: {
required: true
},
phone: {
required: true,
phoneUS: true
}
},
messages: {
id: {
required: "Please enter ID number."
},
password: {
required: "Please enter password."
},
phone: {
phoneUS: "Please enter a valid phone number."
}
}
});
});
$('#calculator-submit-btn').click(function() {
var fuel_amount = $('#fuel-amount-field').val();
var burn_rate = $('#burn-rate-field').val();
var time_empty = fuel_amount * burn_rate;
time_empty = time_empty.toFixed(2);
$('#time-empty-field').val(time_empty);
});
submit() can be used on submit forms only.
for more details chec jQuery API : http://api.jquery.com/submit/
Simply you cannot attach submit() event to a button , only to a form.

jQuery validation don't work after add and input

I've a form where I have rows to an table manually.
This row need and input (required) and have two select...
The problem is, if I add more than one row the submit validation for the table don't work for the second (and subsequent rows)...
Javascript code:
$('#classAdd').click(function(e){
e.preventDefault();
//trainingAction.addRow(schoolGroups[0].schoolGroupId, -1, '');
//add one line
$('#classes > tbody:last').append('<tr><td><input class="required datepicker classStartDate" name="classStartDate" /></td>'+
'<td><select class="classSchoolGroupId"></select></td>'+
'<td><select class="classSchoolId"></select></td>'+
'<td><i class="icon-remove"></i></td></tr>');
var last = $('#classes tr:last');
var csgi = last.find('.classSchoolGroupId');
var csi = last.find('.classSchoolId');
var input = last.find('.classStartDate');
//append values
trainingAction.appendArrayToSelect(csgi, schoolGroups, 'schoolGroupId', 'schoolGroupName', -1);
//append values
trainingAction.appendArrayToSelect(csi, schoolGroups[0].getSchools(), 'Value', 'Text', -1);
//add event
trainingAction.schoolGroupChange(csgi);
//rebind datepicker
helpers.bindDatepicker();
//rebind validators
$('form').validate();
$(input).rules('add', {
required: true
});
//rebind remove button
trainingAction.removeClass();
});
I try the code above like the suggested here (jQuery validate - group inputs with similar rules).
Another snippet that I try and don't work (based on this post jquery validation rules)
$('form').validate({
rules:{
classStartDate: {
required:true
}
}
});
Any suggestion to resolve this issue?
Thanks in advance!
EDIT:
jQuery version: 2.0
If you duplicate with the same name on the input only the first one is validated, you need to add the brackets to the name like this
<input class="required datepicker classStartDate" name="classStartDate[]" />
And the javascript
$('form').validate({
rules:{
"classStartDate[]": {
required:true
}
}
});
hope i can help in something

Categories