Checkbox element disappears from serialize() when not checked - javascript

I have a form/input checkbox like so:
<form id="the_form">
<input name="my_checkbox" type="checkbox" value='true' />
</form>
When I run a $("#the_form").serialize(); my_checkbox only comes up as true when it is checked. If it is not checked, there is no data that comes with my_checkbox.
Is there a way I can make it so if the data is not checked, it'll at least give a null value to my_checkbox or something?

This is normal behavior for HTTP form posts from web browsers: checkbox values are not presented when not checked, since you can infer their value from their absence.
Frankly, this is can be solved with plain engineering: the code that presents the form knows if the checkbox should be present, so the code that receives the post should also know that the checkbox should be present and can implicitly determine the correct, non-checked, value of the checkbox.
If you will give me an indication of your back end technologies I may be able to provide some ideas for how you might engineer the presence of a value for non-checked checkboxes in your form data collection.
If you truly must have the value posted, which I consider less than ideal, then you can add a hidden input that mirrors the value of your checkbox and which is updated by JavaScript:
<form id="the_form">
<input id="my_checkbox_ui" name="my_checkbox_ui" type="checkbox" value='true' />
<input id="my_checkbox" name="my_checkbox" type="hidden" value='true' />
</form>
<script>
$(document).ready(function () {
$('#my_checkbox_ui').change(function () {
$('#my_checkbox').val($(this).val());
});
});
</script>
Keep in mind that doing this when not absolutely needed creates extra complexity and yields a poorer system:
The form post will be larger, using more bandwidth
The simple correspondence between visible elements and underlying posted elements is broken, a possible source of confusion and mistakes for future developers working with this code.
The need for JavaScript creates additional surface area of possible breakage--there are more moving parts that can break and this causes fragility.
Related to the two previous points, if someone copies the form and tries to use it in other code, it won't work correctly, even though the UI looks like it is working.
Another way that you could possibly solve this is to semi-unobtrusively injection the the checkbox-shadowing elements with javascript:
<form id="the_form">
<input id="my_checkbox_ui" name="my_checkbox_ui" type="checkbox" value='true' />
<input id="my_checkbox" name="my_checkbox" type="hidden" value='true' />
</form>
<script>
function getShadowFn(id, shadowId) {
return function() {
$('#' + shadowId).val($('#' + id).val());
};
}
function convertCheckboxesToAlwaysPostingCheckboxes() {
$('input[type="checkbox"]').each(function(id, el) {
var $el = $(el);
var name = $el.prop('name');
var id = $el.prop('id');
var shadowId = id + '_shadow'
$el.prop('name', name + '_ui');
$('<input type="hidden" id="' + shadowId + '" name="' + name + '">')
.insertAfter($el);
$el.change(getShadowFn(id, shadowId));
});
}
$(document).ready(convertCheckboxesToAlwaysPostingCheckboxes);
</script>
This is still added complexity, but it is less fragile because it is no longer specific to any checkbox, and all the checkboxes will now work correctly with just this one bit of code (though I didn't test it at all, so please take it as inspiration rather than prescription). So you can get this code working right, and then use it over and over.

I submit my checkbox through javascript, and since I parse a lot of information in the backend, and my script looks for these variables, it didn't seem like an appropriate solution to do this after the form was submitted.
Thanks to everyone that gave me guidance, but I figured out a way to solve this without too much heavy lifting.
function submitForm()
{
//serialize all the inputs in the form
var data_serialize = $("#the_form").serialize();
//check to see if any checkbox's are not checked, and if so, make them false
$("#the_form input:checkbox:not(:checked)").each(function(e){
data_serialize += "&"+this.name+'=false';
});
//submit the form
var url = "/submit";
$.ajax({ type: "POST", url: url, data: data_serialize,
success: function(data) { },
error: function(data) { }
});
return false;
}

Related

Javascript to "copy in real time" some fields from a form to another form (with different input names)

I'm trying to write a function to copy some fields (in real time) from a specific form, to another form
I try to be more specific:
I have 2 forms
- The first form is the one the user will fill in.
- The other form is hidden.
When the user will fill the first form, the second form (hidden) will be filled by the same informations.
Some fields are automatically filled by some calculations, so I can't use keyup/keypress or "click" to start the function
I wrote something like this, but it doesn't work
$(function(){
var form1 = $('#form1'),
form2 = $('#form2');
$('#fieldname_form1').change(function(){
$('input[name="inputname2"]', form2).val(function(){
return $('input[name="inputname1"]', form1).val();
});
});
});
You can copy in real time using the keyup function, something like this. Otherwise, when you say
Some fields are automatically filled by some calculations
What do you mean? These calculations are made by you using JS or what? Because, if you are using JS you can fill the two fields at the same time when you make the calculations.
this works for me...
$(function() {
$('#i1').change(function(evt) {
$('#i2').val(evt.target.value);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<input type="text" name="name1" id="i1" />
</form>
<form>
<input type="text" name="name2" id="i2" />
</form>
The change event is fired after the element has lost the focus. For the "user editable" elements you should use keyup (for the textbox) and change for the drop down elements.
On the other hand, for the fields filled automatically, you don't have any nice and clean solutions. I can think in two options:
If the calculations trigger is always the user changing some value, you could copy every form value after that happens.
(very bad option, but it would still work) You could be constantly checking for changes in every element and copying them using setInterval function.
As a side note
As well as your code should work, there is a simpler way to do it:
$('#fieldname_form1').change(function(){
var value = $('input[name="inputname1"]', form1).val();
$('input[name="inputname2"]', form2).val(value);
});
This should work -
$(function() {
var form1 = $('#form1'),
form2 = $('#form2');
$('#fieldname_form1').change(function() {
$('input[name="inputname2"]', form2).val($(this).val());
});
});

genvalidator: check for checkbox in form validation

I'm using genvalidator to have some tests on input fields in a form. Problem is I can't find a way to test if a checkbox has been checked. This is how all the fields are set:
frmvalidator.addValidation("name","req","Insert your name");
frmvalidator.addValidation("city","req","Insert your city");
frmvalidator.addValidation("phone","req","Insert your phone number");
This is my checkbox
<input type="checkbox" name="agree" id="agree "value="yes"/>
How can I make it mandatory with genvalidator?
This is the part that handles the form process (in short: if there aren't errors, it's ok):
if(empty($name)||empty($city)||empty($phone)||BLAHBLAH)
{
$errors .= "\n Mandatory field. ";
}
if(empty($errors))
{
// send the email
}
It tried with this JS code with no luck:
function validate(form) {
if(!document.form1.agree.checked){alert("Please check the terms and conditions");
return false; }
return true;
}
If possible I'd like to use genvalidator functions. :)
You are expending a lot of energy trying to make the javascript plugin work.
Would you consider working with jQuery? If you haven't yet kicked its tires, it's a lot easier than it sounds -- and much more uniform / faster to type than plain js.
To use jQuery, you only need to include the jQuery library in the document, usually in the head tags thus:
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
</head>
Then, you can easily create you own verification routines, with FULL control over what you are doing.
Here is a working example for you to study. As you can see, the code is pretty minimal.
When the Submit button (#mysub) is clicked, we quickly check each field to see if it validates. If any field fails validation, we can return control to the user with the field colored and in focus.
If all fields pass validation, then we issue the submit() method on the form ID, and off it goes (to the location specified in the action="somepage.php" attribute).
Note that I added some quick/dirty code at bottom to remove any css colorization from failed validations. This code runs every time a field is exited, regardless whether the field has validation coloring or not. This is not very efficient (although it certainly won't hurt anything) and is only intended to demonstrate what is possible.
Hmmmmm. I think it would be more efficient to have a class with certain attributes, and add/remove that class if fail validation. Okay, I liked that idea enough that I created a new jsFiddle using that method to demonstrate what that would look like.
jsFiddle here
HTML:
<form id="fredform">
First Name: <input id="fname" name="fname" type="text"/>
Last Name: <input id="fname" name="fname" type="text"/>
Email: <input id="fname" name="fname" type="text"/>
<input id="mysub" type="button" value="Submit" />
</form>
jQuery:
arrValidate = ['fname','lname','email']
$('#mysub').click(function() {
var nextFld, i ;
for (i=0; i<arrValidate.length; i++){
nextFld = arrValidate[i];
if ( $('#'+nextFld).val() == '') {
alert('Please complete all fields. You missed the [' +nextFld+ '] field.');
$('#'+nextFld).css({'border':'1px solid red','background':'yellow'});
$('#'+nextFld).focus();
return false;
}
}
//if it gets here, all is okay: submit!
$('#fredform').submit();
});
//Remove any css validation coloring
$('input:not([type=button])').blur(function(){
$(this).css({'border':'1px solid lightgrey','background':'white'});
});
Note that there is also a jQuery validation plugin that looks very professional. I haven't played with it myself, always preferring to code my own stuff, but here is the link:
http://jqueryvalidation.org/documentation/
Note the very cool demo
Just so you know what to expect: implementing this plugin would be more difficult than the methodology I suggested above.
` ANSWER TO YOUR COMMENT QUESTION: `
Regarding your comment and the code posted at pastebin:
(Sorry for the long answer, but I want it to be clear. Please read carefully.)
(1) Please wrap your javascript code in a document.ready function. This is my fault; I should have added it to my code example. Otherwise, the code will execute before the DOM fully exists and event triggers will not be bound to the controls (because they do not yet exist in the DOM). Therefore:
arrValidate = ['checkbox']; //a global variable
$(document).ready(function() {
$('#submit').click(function() {
var nextFld, i ;
for (i=0; i<arrValidate.length; i++){
nextFld = arrValidate[i];
if ( $('#'+nextFld).val() == '') {
alert('Please complete all fields. You missed [' +nextFld+ ']');
$('#'+nextFld).css({'border':'1px solid red','background':'yellow'});
$('#'+nextFld).focus();
return false;
}
}
//if it gets here, all is okay: submit!
$('#contact_form').submit();
}); //END #submit.click
}); //END document.ready
(2) Your checkbox still has the value="yes" attribute that breaks the javascript. Please change this:
<input type="checkbox" name="checkbox" id="checkbox" value="yes" /> <small>Ho
to this:
<input type="checkbox" name="checkbox" id="checkbox" /> <small>Ho
(3) There is no need to have type="submit" for your <input value="Invia"> button, nor is there a need for a name= attribute on that control.
First the name= attribute: it is only useful when passing data from that control to the PHP(?) file that processes your form: ($_SERVER['SCRIPT_NAME']). The name= part is the variable name, and the value of the control is the variable value. The button has no data to pass along, so does not need to have a variable name assigned to it.
Next, the type="submit": This is not required, because you can use jQuery to submit the form any time you want. In the old days, before javascript/jQuery, we had forms. Back in those days, the only way to make the form submit was to use the type="submit" attribute. There was no such command as: $('#myFormId').submit(); -- but today there is. So change that attribute to type="button" and let jQuery submit the form for you. Trust me, this works!
Another thing to consider: once you use type="submit" you must deal with the form's default actions when clicking that button. You cannot simply return control to the user when there is an error, because the form has been told to submit. (You must use event.preventDefault() to override the default behaviour -- you can read about that later.)
(4) Checkbox values must be checked using one of these methods. Checkboxes do not have a value. This is my fault again, I should have written a checkbox into my example.
$('#submit').click(function() {
var nextFld, i ;
//Validate the checkbox:
if ( $('#checkbox').is(':checked') == false ) {
alert('You must read the informativa and check the checkbox at bottom of form');
return false;
}
//Validate the rest of the fields
for (i=0; i<arrValidate.length; i++){
(5) jQuery's submit() method won't work IF any element uses =submit as either its name= or id= attribute.
This is a weird thing, but you need to know it. I just learned it (again) while troubleshooting my jsFiddle example.
If you want to use jQuery to submit your form (and we do) via the .submit() method, then no element in your form can have the name= or id= attribute set to "submit". The INPUT button had both name= and id= set to submit; that is why it wasn't working.
Reference: http://blog.sourcecoder.net/2009/10/jquery-submit-on-form-element-does-not-work/
See the revised code example in the jsFiddle:
Revised jsFiddle here
Please Please Please study the above jsFiddle. You should be able to dump the genvalidator plugin entirely. If you understand the jsFiddle completely, you will be in a new place as a programmer.
If you're using jQuery, try checking this way:
function validate(form) {
if(!$('[name="agree"]').prop('checked')){
alert("Please check the terms and conditions");
return false;
}
return true;
}
or try using
function validate(form) {
if(!$('[name="agree"]')[0].checked){
alert("Please check the terms and conditions");
return false;
}
return true;
}
This is untested but I think it would look something like this:
function DoCustomValidation() {
var frm = document.forms["myform"];
if(document.form1.agree.checked != true) {
sfm_show_error_msg('The Password and verified password does not match!',frm.pwd1);
return false;
}else{
return true;
}
}
Note that you must customize this line to have the correct name of your own form:
var frm = document.forms["myform"];
Plus, you also need to associate the validation function with the validator object:
frmvalidator.setAddnlValidationFunction("DoCustomValidation");
Source: genvalidator documentation
Since you've tagged the question with JQuery, this should work for you:
function validate(form) {
if ($("#agree :checked").length < 1) {
alert("Please check the terms and conditions");
return false;
}
return true;
}
I tend to use this approach because it also works for multiple checkboxes or radio button groups as well. Note, however, that it does not care about what was checked, just that something was checked . . . in the case of a single checkbox, this acts as a "required to be checked" validation as well.
Add a new div for error location above your input tag like this :
<div name="formname_inputname_errorloc" class="errorstring">
//<your input tag goes here>
Make sure u have the css for errorstring class in your css file. and the other req js files
Try to search the demo for gen validator it has been totally explained in the demo
frmvalidator.addValidation("agree","selmin=1","Please select checkbox");

How to get websites actual HTML code by JS?

I have a website with a form. The form is filled by user with data for example i show to user:
<input type='text' value="" name="dsa" />
And he fills it with value of "3";
And he clicks button "save". Now i want to have the whole HTML of the website including values of fields. So i use:
document.documentElement.innerHTML
But i get:
<input type='text' value="" name="dsa" />
But i want to get this:
<input type='text' value="3" name="dsa" />
NOTICE I want to take the whole HTML of the website, not only one field. I dont know what fields will be on the website so i need a general solution.
AFAIK you can't get this from the HTML code, as the HTML code does not change when the user inputs something in a Input text field.
What you could do is get all input fields on the page and get their values with something like this:
var inputs, index;
inputs = document.getElementsByTagName('input');
for (index = 0; index < inputs.length; ++index) {
// deal with inputs[index] element.
}
The code is from this post: https://stackoverflow.com/a/2214077/312312
I was too lazy to write it down my self :P
In jQuery I do
$(function() {
$('input').keyup(function() {
$(this).attr('value', $(this).val());
});
});​
Because the value attribute isn't set after key up
You could try to set a live event on a whole document that will set attribustes to html with values user set in or set them on your submit.
First way for example
$("body").on("change", "select,input,textarea", function(){
$(this).attr("value", $(this).val());
});
But this should not be done so blindly, and you'll get problems with reset. And you should solve problem with selected radio, checkbox and other attributes, not only values.
Second way is to serialize whole page when it really needed.
var serialize = function(el){
$("select, input, textarea").each(function(){
$(this).attr("value", $(this).val()); //the same way as upper
});
}
$(".serialize").click(function(){
var inner = $("body"),
html;
serialize(inner);
html = inner.html(); //here you will get whole html with setted attributes
});
This way seems to be better because there wont be delegation of unnecessary event.
http://jsfiddle.net/CeAXL/2/ - test example.
But in both ways it's not good idea to set permanent values to DOM itself.

jquery: get selected checkboxes, put in array, delimit the array and output to dynamic html button

I want to have a web button that is generated dynamically depending on which checkboxes a user selects, without needing to reload the page. I guess jQuery is the way to do this but I am a complete noob with jQuery/JavaScript (trying to learn on the fly, which isn't easy).
Ultimately, I think it s/b a 2-step process: (1) as the user checks checkboxes, store them in an array and delimit them, and (2) output html to create a button that dynamically uses the delimited array values.
HTML form:
<input type="checkbox" name="catChoices[]" value="80s" />80s<br />
<input type="checkbox" name="catChoices[]" value="90s" />90s<br />
<input type="checkbox" name="catChoices[]" value="00s" />00s<br />
Being a jQuery/JS novice, I've only come up with this to do step 1 mentioned above. I don't know if this is on the right track or completely off:
jQuery:
$(document).ready(function() {
$("input").click(function() {
var checkValues = $('input[name=catChoices]:checked').map(function() {
return $(this).val();
}).get();
str = checkValues.join(',');
});
});
I also don't know how to incorporate step 2 (get the button to be created dynamically with jQuery). The solutions I've googled show how to pass the values to html/PHP, which requires a page refresh, but I want the button to update on-the-fly as the user checks/unchecks checkboxes.
Thanks for your help!
Are you sure you want to use such a non-standard (for the web) format?
Have you thought about doing this:
var data = $('input[name="catChoices[]"]').serialize();
This is smart enough to only include checked checkboxes.
Granted, you can always convert it to a comma-separated list by doing
data = data.replace(/&/g, ',').replace(/catChoices%5B%5D=/g, '')
Creating a button is as simple as:
$('<button>', { val: data })
or
$('<input>', { type: 'submit', val: data })
a different api is preferred by some:
$('<input type="submit">').val(data)
Try this. Name of the input box is catChoices[] and it should be in quotes.
$("input").click(function() {
var checkValues = $('input[name="catChoices[]"]:checked').map(function() {
return $(this).val();
}).get();
str = checkValues.join(',');
alert(str );
});

Using depends with the jQuery Validation plugin

I've got a form with a bunch of textboxes that are disabled by default, then enabled by use of a checkbox next to each one.
When enabled, the values in these textboxes are required to be a valid number, but when disabled they don't need a value (obviously). I'm using the jQuery Validation plugin to do this validation, but it doesn't seem to be doing what I expect.
When I click the checkbox and disable the textbox, I still get the invalid field error despite the depends clause I've added to the rules (see code below). Oddly, what actually happens is that the error message shows for a split second then goes away.
Here is a sample of the list of checkboxes & textboxes:
<ul id="ItemList">
<li>
<label for="OneSelected">One</label><input id="OneSelected" name="OneSelected" type="checkbox" value="true" />
<input name="OneSelected" type="hidden" value="false" />
<input disabled="disabled" id="OneValue" name="OneValue" type="text" />
</li>
<li>
<label for="TwoSelected">Two</label><input id="TwoSelected" name="TwoSelected" type="checkbox" value="true" />
<input name="TwoSelected" type="hidden" value="false" />
<input disabled="disabled" id="TwoValue" name="TwoValue" type="text" />
</li>
</ul>
And here is the jQuery code I'm using
//Wire up the click event on the checkbox
jQuery('#ItemList :checkbox').click(function(event) {
var textBox = jQuery(this).siblings(':text');
textBox.valid();
if (!jQuery(this).attr("checked")) {
textBox.attr('disabled', 'disabled');
textBox.val('');
} else {
textBox.removeAttr('disabled');
textBox[0].focus();
}
});
//Add the rules to each textbox
jQuery('#ItemList :text').each(function(e) {
jQuery(this).rules('add', {
required: {
depends: function(element) {
return jQuery(element).siblings(':checkbox').attr('checked');
}
},
number: {
depends: function(element) {
return jQuery(element).siblings(':checkbox').attr('checked');
}
}
});
});
Ignore the hidden field in each li it's there because I'm using asp.net MVC's Html.Checkbox method.
Using the "ignore" option (http://docs.jquery.com/Plugins/Validation/validate#toptions) might be the easiest way for you to deal with this. Depends on what else you have on the form. For i.e. you wouldn't filter on disabled items if you had other controls that were disabled but you still needed to validate for some reason. However, if that route doesn't work, using an additional class to filter on (adding and removing with your checkboxes) should get you to where you want to go, but easier.
I.e.
$('form').validate({
ignore: ":disabled",
...
});
Usually when doing this, I skip 'depends' and just use the required jQuery Validate rule and let it handle the checking based on the given selector, as opposed to splitting the logic between the validate rules and the checkbox click handler. I put together a quick demo of how I accomplish this, using your markup.
Really, it boils down to required:'#OneSelected:checked'. This makes the field in question required only if the expression is true. In the demo, if you submit the page right away, it works, but as you check boxes, the form is unable to submit until the checked fields are filled with some input. You could still put a .valid() call in the checkbox click handler if you want the entire form to validate upon click.
(Also, I shortened up your checkbox toggling a bit, making use of jQuery's wonderful chaining feature, though your "caching" to textBox is just as effective.)
Depends parameter is not working correctly, I suppose documentation is out of date.
I managed to get this working like this:
required : function(){ return $("#register").hasClass("open")}
Following #Collin Allen answer:
The problem is that if you uncheck a checkbox when it's error message is visible, the error message doesn't go away.
I have solved it by removing the error message when disabling the field.
Take Collin's demo and make the following changes to the enable/disable process:
jQuery('#ItemList :checkbox').click(function()
{
var jqTxb = $(this).siblings(':text')
if ($(this).attr('checked'))
{
jqTxb.removeAttr('disabled').focus();
}
else
{
jqTxb.attr('disabled', 'disabled').val('');
var obj = getErrorMsgObj(jqTxb, "");
jqTxb.closest("form").validate().showErrors(obj);
}
});
function getErrorMsgObj(jqField, msg)
{
var obj = {};
var nameOfField = jqField.attr("name");
obj[nameOfField] = msg;
return obj;
}
You can see I guts remove the error message from the field when disabling it
And if you are worrying about $("form").validate(), Don't!
It doesn't revalidate the form it just returns the API object of the jQuery validation.
I don't know if this is what you were going for... but wouldn't changing .required to .wasReq (as a placeholder to differentiate this from one which maybe wouldn't be required) on checking the box do the same thing? If it's not checked, the field isn't required--you could also removeClass(number) to eliminate the error there.
To the best of my knowledge, even if a field is disabled, rules applied to it are still, well, applied. Alternatively, you could always try this...
// Removes all values from disabled fields upon submit
$(form).submit(function() {
$(input[type=text][disabled=disabled]).val();
});
I havent tried the validator plugin, but the fact that the message shows for a splitsecond sounds to me like a double bind, how do you call your binders? If you bind in a function try unbinding just before you start, like so:
$('#ItemList :checkbox').unbind("click");
...Rest of code here...
Shouldn't validate the field after disabling/enabling?
jQuery('#ItemList :checkbox').click(function(event) {
var textBox = jQuery(this).siblings(':text');
if (!jQuery(this).attr("checked")) {
textBox.attr('disabled', 'disabled');
textBox.val('');
} else {
textBox.removeAttr('disabled');
textBox[0].focus();
}
textBox.valid();
});
I had the exact same problem.
I solved this by having the radio-button change event handler call valid() on the entire form.
Worked perfect. The other solutions above didn't work for me.

Categories

Resources