I want to validate my form using jQuery.
It has groups of radio buttons.
I have found multiple solutions for a single group of radio-buttons or solutions, where you have to specifically say what group-names there are.
Like here:
Validate radio buttons with jquery?
The problem is, that the form is being generated at run-time.
The questions are saved in a txt file (don't ask, it's a school exercise).
The generated HTML-Code looks something like this:
<p>What's your gender?
<input type="radio" name="gender" value="m" />Male
<input type="radio" name="gender" value="f" />Female
</p>
<p>
How satisfied are you with out support?
<input type="radio" name="satisfaction" value="0%" />Not at all
<input type="radio" name="satisfaction" value="25%" />Not very much
<input type="radio" name="satisfaction" value="75%" />It was ok
<input type="radio" name="satisfaction" value="100% />It was very satisfying
</p>
The js file is being generated using Twig, so it would be possible to loop through all the radio button groups, but I would like to avoid this if that's possible.
You would need to add all the groups first (page load would be fine, but make sure the group array is in global scope), then validate each group individually when your form is submitted/button click
var groups = [];
$(function() {
$("input[type=radio][name]").each(function() {
// Add the unique group name to the array
groups[$(this).attr("name")] = true;
});
});
$("button").click(function() {
$.each(groups, function(i, o) {
// For each group, check at least one is checked
var isValid = $("input[name='"+i+"']:checked").length;
alert(i + ": " + isValid);
});
});
I got it working like this
var groups = [];
$(function() {
$("input[type=radio][name]").each(function() {
// Add the unique group name to the array
if (groups[groups.length - 1] != $(this).attr("name")) groups.push($(this).attr("name"));
});
});
$('form').submit(function () {
var isValid = true;
$.each(groups, function(i, o) {
// For each group, check at least one is checked
if (isValid) isValid = $("input[name='"+o+"']:checked").length;
});
if (!isValid) return false;
return true;
});
Thanks to Blade0rz!
Related
I have a web page which asks the user two simple yes-no questions. Under each question there's a set of two radio buttons in which the user can choose either yes or no.
<p>Question 1 yes or no?</p>
<input type="radio" name="q1" id="q1-y" value="Yes">Yes
<input type="radio" name="q1" id="q1-n" value="No">No
<p>Question 2 yes or no?</p>
<input type="radio" name="q2" id="q2-y" value="Yes">Yes
<input type="radio" name="q2" id="q2-n" value="No">No
If the user chooses yes for BOTH questions, it needs to display some HTML which will provide a link to a certain page. If the users answers no to one or both of the questions, then some alternative HTML will appear which will display another message.
There can't be a submit button like a form and this has to be a javascript/jquery based solution, not server side. The page needs to:
1) Detect when both sets of questions have been answered. Then
2) Instantly display certain HTML depending on if either a) YES has been answered to both, or b) if a NO has been given once or more.
Essentially, the logic should be something along the lines of:
if( /*both radio buttons answered*/ ){
if( /*both answers are yes*/ ){
/*show HTML set 1*/
} else {
/*show HTML set 2*/
}
}
I have tried looking at questions on this site, but I can't seem to find a solution to this specific problem. Let me know if anything needs clarifying.
Thanks very much!
Different solution:
$( "input" ).change(function() {
var buttons = jQuery("input:radio:checked").get();
var values = $.map(buttons, function(element) {
return $(element).attr("value");
});
if(values == "Yes,Yes") {
alert("both yes");
}
else {
//do something else
}
});
Demo: Multiple Radiobuttons
Don't like to check the string like that but could be adjusted in a proper way.
Try this:
$(document).ready(function(){
$("#yep").hide();
$("#nope").hide();
$(".nones").click(function(){
$("#yep").hide();
$("#nope").show();
});
$(".yipis").click(function(){
var checkeo = 1;
$( ".yipis" ).each(function( index ) {
if($(this).is(":checked") == false)
{
checkeo = 0;
};
});
if(checkeo){
$("#nope").hide();
$("#yep").show();
}
});
});
Working fiddle: http://jsfiddle.net/robertrozas/84o46mqd/
Here is a possible way to access the values you want. JSFiddle
HTML
<p>Question 1 yes or no?</p>
<input type="radio" name="q1" id="q1-y" value="Yes">Yes
<input type="radio" name="q1" id="q1-n" value="No">No
<p>Question 2 yes or no?</p>
<input type="radio" name="q2" id="q2-y" value="Yes">Yes
<input type="radio" name="q2" id="q2-n" value="No">No
<p>
<input type="button" id="finished" value="Submit" />
</p>
<div id="htmlarea"></div>
JavaScript
I find that jQuery is() function and the pseudo class :checked are helped when reading radio buttons.
$("#finished").click(function() {
var q1y = $("#q1-y").is(":checked");
var q1n = $("#q1-n").is(":checked");
var q2y = $("#q2-y").is(":checked");
var q2n = $("#q2-n").is(":checked");
if (q1y && q2y) {
$("#htmlarea").html("Both yes");
} else if (q1n && q2n) {
$("#htmlarea").html("Both no");
} else {
var html = "";
if (q1y) html += "Q1 yes. ";
if (q1n) html += "Q1 no. ";
if (q2y) html += "Q2 yes. ";
if (q2n) html += "Q2 no. ";
if (html=="") html = "None selected";
$("#htmlarea").html(html);
}
});
Instead of setting the HTML text, use window.location.href = "http://someurl.com"; if you want to redirect to another webpage.
One approach, given the following HTML (note the custom data-* attributes in the appended <div> elements, used to identify which choice those elements relate to):
<p>Question 1 yes or no?</p>
<input type="radio" name="q1" id="q1-y" value="Yes" />Yes
<input type="radio" name="q1" id="q1-n" value="No" />No
<p>Question 2 yes or no?</p>
<input type="radio" name="q2" id="q2-y" value="Yes" />Yes
<input type="radio" name="q2" id="q2-n" value="No" />No
<div class="result" data-relatesTo="Yes">All choices are 'yes'</div>
<div class="result" data-relatesTo="No">All choices are 'no'</div>
Which works with the following jQuery:
// caching the radio elements on the page:
var radios = $('input[type="radio"]'),
// getting the number of unique radio 'groups':
radioGroups = $.unique($('input[type="radio"]').map(function () {
return this.name;
}).get());
// binding an anonymous function as a change-event handler:
radios.change(function () {
// getting all the checked radio inputs:
var checked = radios.filter(':checked'),
// creating an object that maps to the relevant values/choices to be made:
choice = {
'yes': checked.filter(function () {
return this.value.toLowerCase() === 'yes';
}).get(),
'no': checked.filter(function () {
return this.value.toLowerCase() === 'no';
}).get()
};
// if all groups have a checked radio input:
if (checked.length === radioGroups.length) {
// iterate over the '.result' div elements:
$('div.result').each(function (i, el) {
// using 'toggle(switch)' to show/hide the element,
// the switch tests whether the choice related to the current
// element is equal to the number of radioGroups. If it is,
// it's shown, otherwise it's hidden.
$(this).toggle(choice[el.getAttribute('data-relatesTo').toLowerCase()].length === radioGroups.length);
});
}
});
JS Fiddle demo.
Alternatively, with the same HTML, the following jQuery approach also works:
var radios = $('input[type="radio"]'),
radioGroups = $.unique($('input[type="radio"]').map(function () {
return this.name;
}).get());
radios.change(function () {
var checked = radios.filter(':checked'),
// getting all the unique chosen values (in lowercase):
opts = $.unique(checked.map(function(){
return this.value.toLowerCase();
}).get());
if (checked.length === radioGroups.length) {
// hide all the '.result' elements:
$('div.result').hide()
// filter the 'div.result' elements:
.filter(function(){
// if the number of opts (chosen values) is 1
// (all choices are the same) and the 'data-relatesTo' attribute
// of the current element we're filtering is equal to that single
// option, then the element is retained in the selector
return opts.length === 1 && this.getAttribute('data-relatesTo').toLowerCase() === opts[0].toLowerCase();
})
// and so we show it:
.show();
}
});
JS Fiddle demo.
References:
JavaScript:
Element.getAttribute().
String.prototype.toLowerCase().
jQuery:
$.unique().
each().
filter().
get().
hide().
map().
show().
toggle().
There are checkboxes, which belong to Form A:
<input type="checkbox" class="item-selector" name="item[]" value="1" />
<input type="checkbox" class="item-selector" name="item[]" value="2" />
<input type="checkbox" class="item-selector" name="item[]" value="3" />
<!-- etc. -->
Then I have Form B that needs the checkbox values from Form A. Form A might have other input fields too, but I'm not interested in those. I only care about $('input.item-selector'). I'm going about it like this:
var postData = $('#form-a').serializeArray();
var items = $('.item-selector:checked').map(function(){
return this.value;
}).get();
if(items.length > 0) {
postData.push({name: 'itemId', value: items});
}
But this way of adding stuff to the postData doesn't seem to work, because the PHP script I send the form to can not find the itemId. Interestingly this does work:
postData.push(name: 'aName', value: 'notAnArrayButAStringValue');
I also tried a couple of solutions like this one: http://benalman.com/projects/jquery-misc-plugins/#serializeobject but the problem with them is that, while they otherwise work fine, for some reason if there are checkboxes in Form B, the checkbox values of Form B are parsed incorrectly and result in null values and loss of data. That would look like this:
var postData = $(this.form).serializeObject();
var items = $('.item-selector:checked').map(function(){
return this.value;
}).get();
if(items.length > 0) {
postData.itemId = items;
}
Using JSON.stringify revealed the object structure to be like this:
{
"name":"Simon J. Kok",
"address_id":"39669",
"email":"*****",
"content_id":"21921",
"client_id":"42101",
"is_ebill":["","1"], <-- this is a checked checkbox
"is_banned":"", <-- this is an unchecked checkbox
"button":"save"
}
The checkboxes in Form B look like
<input type="checkbox" value="1" name="is_ebill" />
<input type="checkbox" value="1" name="is_banned" />
So what I need is either some insight on how to add the checkboxes from Form A to the $.serializeArray() result array -OR- a way to solve the issue of a checked checkbox returning an array when using Ben Alman's plugin.
Here's one approach. First it requires a hidden field in form-b:
<input type="hidden" id="itemId" name="itemId" value="" />
This would be populated with the item-selector data when the form is submitted:
$('#form-b').on('submit', function() {
var checkedValues = [];
$('.item-selector:checked').each(function() {
checkedValues.push($(this).val());
});
$('#itemId').val(checkedValues.join(','));
console.debug('Form B data:', $('#form-b').serializeArray());
});
Adjust the syntax to suit your idiom. Here's a fiddle to demonstrate:
http://jsfiddle.net/klenwell/12evxfvc/
Actually I kinda answered my own question already when I asked it. I used JSON.Stringify to output the JSON formatted string of what $.serializeArray() returned and it became apparent what the structrure needed to work. So here is how to add array values one by one to an array retrieved using $.serializeArray():
var items = $('.item-selector:checked').map(function(){
return this.value;
}).get();
$.each(items, function(i, v){
postData.push({name: 'itemId[]', value: v});
});
I have a poll with a couple a questions. Here is html code
<form id="pool">
<div class="questions>
<input type="radio" name="sex">Male
<input type="radio" name="sex">Female
</div>
<div class="questions>
<input type="radio" name="hair">Brown
<input type="radio" name="hair">Blonde
</div>
.... a lot of qestions div's
</form>
What to do so after the form is submitted to be sure that there is a checked radio button in all div`s ?
If you know how many groups you have you can just do:
if($('#pool input:radio:checked').length < numGroups){
// At least one group isn't checked
}
Otherwise you need to count the number of groups first. I can't think of any way to do this better then:
var rgroups = [];
$('#pool input:radio').each(function(index, el){
var i;
for(i = 0; i < rgroups.length; i++)
if(rgroups[i] == $(el).attr('name'))
return true;
rgroups.push($(el).attr('name'));
}
);
rgroups = rgroups.length;
if($('#pool input:radio:checked').length < rgroups)
alert('You must fill in all the fields.');
else
alert('Thanks!');
set default values or create handler for submit button and check if some values was checked. If no radio button is checked, show error message and do not submit form ( return false)
Untested code, but this is the idea:
if($('#pool').children().length == $('pool
div').find('#pool input:radio:selected').length) {
//do stuff
}
You can use the jquery validate plugin
from my experience this plugin is very efficient
I have a jquery variable that is storing a comma separated list of id names. I need help writing something in jquery that separates that variable and uses those values to populate a forms checkbox values when the page loads.
so my jquery variable is $storedFormValues that is a comma separated list of values "checkbox1, checkbox, etc."
and my form
<form name="formname" id="formid">
<input type='checkbox' class='catcheck' id='checkbox1' value='checkbox1' name='catselect' />Checkbox 1
<input type='checkbox' class='catcheck' id='checkbox2' value='checkbox2' name='catselect' />Checkbox 2
<input type="submit" name="submit" value="Submit" />
</form>
Any help would be greatly appreciated!
This should do it:
var $storedFormValues = "checkbox3,checkbox5";
$(function() {
$.each($storedFormValues.split(","), function(intIndex, objValue) {
$("#" + objValue).attr("checked", "true");
});
})
See the fiddle: http://jsfiddle.net/xNyww/
Not jQuery, but plain JS: You can use split to separate the values in an array:
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/split
I do not know what do the csv looks like. If it's only one line, e.g:
checkbox1, checkbox7, checkbox2
then use it as:
var checkboxes[] = csvString.split(",");
for (str in checkboxes) {
$("#"+str).yourActionHere();
}
If it's several lines (one per checkbox) , e.g.
checkbox1, true
checkbox2, false
then :
var checkboxes[] = csvString.split(/\r\n|\r|\n/);
for (str in checkboxes) {
var data = str.split(",");
$("#"+data[0]).yourActionHere(data[1]);
}
Live Demo
var storedFormValues = "checkbox1, checkbox3, checkbox4";
$('#formid').children('input[id^=checkbox]').each(function() {
if (storedFormValues.indexOf($(this).attr('id')) != -1) {
$(this).attr('checked', 'checked');
}
});
Note: If you plan on having more than 10 checkboxes, I recommend naming them with a leading zero (ex: checkbox01) otherwise you may run into an issue where checkbox1 matches against checkbox11.
I have several checkboxes and a fake submit button to make an AJAX request:
<form>
<input type="checkbox" value="1"/>
<input type="checkbox" value="2" checked="checked"/>
<input type="checkbox" value="3"/>
<input type="checkbox" value="4" checked="checked"/>
<input type="button" onclick="return mmSubmit();"/>
</form>
Within the mmSubmit() method, I would like to retrieve an array of values that have been selected. Here is what I am currently doing.
mmSubmit = function() {
var ids = [];
$('input[type=checkbox]:checked');.each(function(index) {
ids.push($(this).attr('value'));
});
// ids now equals [ 2 , 4 ] based upon the checkbox values in the HTML above
return false;
};
I'm wondering if there is a shorthand method in jQuery used to retrieve the values into an array, or if what I have is already optimal.
I think this can be accomplished with map. Try the following..
mmSubmit = function() {
var ids = $('input[type=checkbox]:checked').map(function(){
return $(this).val();
}).get();
// ids now equals [ 2 , 4 ] based upon the checkbox values in the HTML above
return false;
};
Take a look at: jQuery Traversing/Map
Well you can use .val() instead of .attr('value').
$.serializeArray() may also do what you want (http://docs.jquery.com/Ajax/serializeArray).
It's needs some optimization, buts generally it is right way. My variant:
mmSubmit = function () {
var ids = [];
$('input[type=checkbox]').each(function () {
if (this.checked) {
ids[ids.length] = this.value;
}
});
return ids;
};
It's little faster.