Select at least 1 checkbox in a loop of checkboxes group - javascript

I'm trying to get this thing work for a while but I guess I need to tweak the code from somewhere. I thought, someone here could better guide me instead of banging my head to my coding screen :)
here's the actual process:
<input type="hidden" name='oneSelectionChk_1'>
<input type="checkbox" name='awp_group_1' id='id1'>
<input type="checkbox" name='awp_group_1' id='id2'>
<input type="checkbox" name='awp_group_1' id='id3'>
<input type="checkbox" name='awp_group_1' id='id4'>
<input type="hidden" name='oneSelectionChk_2'>
<input type="checkbox" name='awp_group_2' id='id5'>
<input type="checkbox" name='awp_group_2' id='id6'>
<input type="checkbox" name='awp_group_2' id='id7'>
<input type="checkbox" name='awp_group_2' id='id8'>
<input type="hidden" name='oneSelectionChk_3'>
<input type="checkbox" name='awp_group_3' id='id9'>
<input type="checkbox" name='awp_group_3' id='id10'>
<input type="checkbox" name='awp_group_3' id='id11'>
<input type="checkbox" name='awp_group_3' id='id12'>
what I'm using for jQuery is:
var chkFields = $("input[name='oneSelectionChk']");
$.each(chkFields, function(i, field){
var groupID = field.id.split('_'); // Getting the ID of the group
var chkGroupBoxes = $('input[name="awp_group_"'+groupID[1]);
if(field.value==1)
{
//$.each(chkGroupBoxes, function(j, thisChkBox){
//alert(thisChkBox.value + " #"+j);
alert( $('input[name="awp_group_"'+groupID[1]).filter(':checked').length);
if($('input[name="awp_group_"'+groupID[1]+':checked').length > 0 )
{
//$.scrollTo( '#awp_container', 1200 );
alert($('input[name="awp_group_"'+groupID[1]+':checked').length+" Selected ");
//alert( "Class AlertMsgText Should be removed Now");
$("#selectInstruction_"+groupID[1]).removeClass("AlertMsgText");
//return
}
else
{
alert($('input[name="awp_group_"'+groupID[1]+':checked').length+" Still not selected ");
//alert("Please select atleat 1 from Option #"+groupID[1]);
$("#selectInstruction_"+groupID[1]).addClass("AlertMsgText");
$.scrollTo( '#awp_container', 1200 );
//return;
}
//});
}
});
This code always giving me 0 length of checkboxes, I'm not sure if I need to loop through again for each checkbox or this might work?
Any quick help should be appreciated!

Try
var chkFields = $('input[name^="oneSelectionChk"]');
$.each(chkFields, function (i, field) {
var groupID = field.name.replace('oneSelectionChk_', '')
var chkGroupBoxes = $('input[name="awp_group_' + groupID + '"]');
if (chkGroupBoxes.filter(':checked').length == 0) {
alert('please select at least one checkbox under: ' + field.name)
}
});
Demo: Fiddle

There is no element with name attribute of oneSelectionChk in your markup, the hidden inputs have name attributes that start with oneSelectionChk, you have to use attribute starts with selector.
In case that elements are siblings you can select the target elements using .nextUntil() method:
var $hidden = $('input[type=hidden]').filter('[name^=oneSelectionChk]');
$hidden.each(function(){
var $chekboxes = $(this).nextUntil('input[type=hidden]'),
$checked = $checkboxes.filter(':checked'),
$unchecked = $chekboxes.not($checked);
});
Using name attributes:
var $hidden = $('input[type=hidden]').filter('[name^=oneSelectionChk]'),
$checkboxes = $('input[type=checkbox]');
$hidden.each(function() {
var n = this.name.split('_')[1];
var $grp = $checkboxes.filter('[name="awp_group_'+ n +'"]');
// ..
});

Related

Removing value from array according to index using splice()

I have 4 checkboxes. I add values of them to an array on check. It looks like this.
Here are the four checkboxes I have.
<input type="checkbox" value="degree">
<input type="checkbox" value="pgd">
<input type="checkbox" value="hnd">
<input type="checkbox" value="advdip">
Once I check all four of them, the array becomes,
["degree", "pgd", "hnd", "advdip"]
When I uncheck a checkbox, I need to remove the value of it from the array according to its correct index number. I used splice() but it always removes the first index which is degree. I need to remove the value from the array according to its index number no matter which checkbox I unselect. Hope someone helps. Below is the code. Thanks in advance!
<input type="checkbox" value="degree">
<input type="checkbox" value="pgd">
<input type="checkbox" value="hnd">
<input type="checkbox" value="advdip">
<script>
function getLevels() {
// get reference to container div of checkboxes
var con = document.getElementById('course-levels');
// get reference to input elements in course-levels container
var inp = document.getElementsByTagName('input');
// create array to hold checkbox values
var selectedValues = [];
// collect each input value on click
for (var i = 0; i < inp.length; i++) {
// if input is checkbox
if (inp[i].type === 'checkbox') {
// on each checkbox click
inp[i].onclick = function() {
if ($(this).prop("checked") == true) {
selectedValues.push(this.value);
console.log(selectedValues);
}
else if ($(this).prop("checked") == false) {
// get index number
var index = $(this).index();
selectedValues.splice(index, 1);
console.log(selectedValues);
}
}
}
}
}
getLevels();
</script>
You used the wrong way to find index in your code. If you used element index, it will avoid real index in your array and gives the wrong output. Check below code, it may be work for you requirement.
<input type="checkbox" value="degree">
<input type="checkbox" value="pgd">
<input type="checkbox" value="hnd">
<input type="checkbox" value="advdip">
<script src="https://code.jquery.com/jquery-3.5.0.min.js" integrity="sha256-xNzN2a4ltkB44Mc/Jz3pT4iU1cmeR0FkXs4pru/JxaQ=" crossorigin="anonymous"></script>
<script>
function getLevels() {
// get reference to container div of checkboxes
var con = document.getElementById('course-levels');
// get reference to input elements in course-levels container
var inp = document.getElementsByTagName('input');
// create array to hold checkbox values
var selectedValues = [];
// collect each input value on click
for (var i = 0; i < inp.length; i++) {
// if input is checkbox
if (inp[i].type === 'checkbox') {
// on each checkbox click
inp[i].onclick = function() {
if ($(this).prop("checked") == true) {
selectedValues.push(this.value);
console.log(selectedValues);
}
else if ($(this).prop("checked") == false) {
// get index number
var index = selectedValues.indexOf(this.value);
selectedValues.splice(index, 1);
console.log(selectedValues);
}
}
}
}
}
getLevels();
</script>
Add change handler to the inputs and use jQuery map to get the values of the checked inputs.
var levels
$('#checkArray input').on('change', function () {
levels = $('#checkArray input:checked').map(function () {
return this.value
}).get()
console.log(levels)
}).eq(0).change()
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<fieldset id="checkArray">
<input type="checkbox" value="degree" checked>
<input type="checkbox" value="pgd">
<input type="checkbox" value="hnd">
<input type="checkbox" value="advdip">
</fieldset>
my approach was to add an event handler that reads all checked values when any of those inputs is clicked and empty the array before loging the response. no need to add any dependencies with this one
Hope this is what you are looking for
function getLevels() {
let checkboxContainer = document.getElementById("checkboxContainer");
let inputs = checkboxContainer.querySelectorAll("input");
let checked = [];
inputs.forEach( (input) => {
checked = [];
input.addEventListener( 'click', () => {
checked = [];
inputs.forEach( (e) => {
e.checked ? checked.push(e.value) : null;
})
console.log(checked);
});
});
}
getLevels();
<div id="checkboxContainer">
<input type="checkbox" value="degree" >
<input type="checkbox" value="pgd">
<input type="checkbox" value="hnd">
<input type="checkbox" value="advdip">
</div>
I don't know if this is what you need, to show an array of the selected values, if you want you can call the function that calculates on the check.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<fieldset id="checkArray">
<input type="checkbox" value="degree" checked>
<input type="checkbox" value="pgd">
<input type="checkbox" value="hnd">
<input type="checkbox" value="advdip">
</fieldset>
<button onclick="getLevels()">getLevels</button>
<script>
function getLevels() {
var levels = [];
$.each($("input:checked"), function() {
levels.push(($(this).val()));
});
console.log(levels);
}
getLevels();
</script>

Javascript checkbox that adds value from another table to the price

Could anybody help me with this problem? I have an input price value that changes when you select different checkboxes, but it doesn't add up.
I don't really know how to fix it that if you select something, it adds to the total price, and when you select another one it adds again.
The foreach is to get all the exa_names from the Extra table with the checkbox and the price from that item.
Javascript
$(document).ready(function(){
$(".option").change(function(){
var id = $(this).attr('id');
console.log(id);
var id_number = id.split("_")[1];
console.log(id_number);
var hidden_input = $(".option_price" + id_number).val();
console.log(hidden_input);
})
});
HTML
<label>Options</label><br>
#foreach($options as $option)
<div>
<input type="checkbox" class="option" id="option_{{ $option->exa_id }}" name="option_{{ $option->exa_id }}" value="{{ $option->exa_id }}" {{ isset($cache) ? (isset($cache['option_' . $option->exa_id]) ? 'checked' : '') : (old() ? (old('option_' . $option->exa_id) ? 'checked' : '') : ($inschrijving ? (in_array($registration->exa_id, $registration_options) ? 'checked' : '') : '')) }} >
<input type="hidden" value="{{ $option->exa_price}}" class="option_price_{{ $option->exa_id }}">
<label>{{ $option->exa_name }}</label>
<label> €{{ $option->exa_price }} </label>
</div>
#endforeach
Html input totalprice(where it has to show the total price)
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label>Total</label>
<input type="text" name="totalprice" id="totalprice" class="form-control" data-blocked="<>{}" value="0" required>
</div>
</div>
</div>
RegistrationController
$options_ids_array = array();
$options = Extra::all();
foreach($options as $option){
$option->exa_id = "option_" . $option->exa_id;
$input_option = $option->exa_id;
if(!is_null($input_option)){
$options_ids_array[] = $input_option;
}
}
$registration->dev_option_id = implode(",", $options_ids_array);
$registration->save();
I think it's better to store the price of your item in a javascript variable (because it prevent to change the value of hidden input and have easy access on js side) and access to your price through your checkbox value (because it is exactly the id you tried to get with id value by split it with _ character). For add price from checked checkboxes (if they are not too much checkboxes), create a check function to detect which of them are checked and then select the price of each and add them to each other, then put it to your price place. Something like:
var options = $(".option");
var options_price = ['your', 'price', 'values', 'according', 'to', 'options', 'id'];
function optionsPrice() {
var total_price = 0;
options.each(function () {
var option = $(this);
if (option.is(':checked') && option.val() != '' && $.inArray(option.val(), Object.keys(options_price))) {
total_price += options_price[option.val()];
}
});
return total_price;
}
Call optionsPrice function on any checkbox change.
OR if you have a lot of checkeboxes on your page,
you can have a global total price variable and add or sub price from it on any checkbox change. Something like:
var total_price = 0;
var options = $(".option");
var options_price = ['your', 'price', 'values', 'according', 'to', 'options', 'id'];
var option, val;
options.on('change', function() {
option = $(this);
val = option.val();
if(val && val != '' && $.inArray(val, Object.keys(options_price)) !== -1) {
if(option.is(':checked')) {
total_price += options_price[option.val()];
} else {
if(total_price > 0) {
total_price -= options_price[option.val()];
} else {
total_price = 0;
}
}
}
});
I hope it helps :)
You've got the tricky part - uniquely identifying your inputs in JS - already done. All that is left is to sum them up!
The simplest option is to iterate over all your inputs whenever one of them changes, and recalculate the price from scratch.
I'm not 100% sure how your inputs and prices and extra costs work, but let's make it simple. Here's some example HTML in the format your Blade template could generate:
<div>
<input type="checkbox" class="option" id="option_1" name="option_1" value="1" checked>
<input type="hidden" value="1" class="option_price_1">
<label>Orange</label>
<label>1</label>
</div>
<div>
<input type="checkbox" class="option" id="option_2" name="option_2" value="2">
<input type="hidden" value="2" class="option_price_2">
<label>Apple</label>
<label>2</label>
</div>
<div>
<input type="checkbox" class="option" id="option_3" name="option_3" value="3" checked>
<input type="hidden" value="3" class="option_price_3">
<label>Pear</label>
<label>3</label>
</div>
<!-- I've added a total area to display the total result -->
<div id="total"></div>
Now taking your code, and using jQuery's .each() to iterate over all inputs on the page:
$('.option').change(function() {
// This is what we'll use to sum the prices
var total = 0;
// Use .each() to iterate over all .option inputs
$('.option').each(function(index) {
// Inside .each, $(this) represents the current element
var id = $(this).attr('id');
var id_number = id.split("_")[1];
// Note your code was missing the _ after price here
var hidden_input = $(".option_price_" + id_number).val();
// Is this option checked? If yes, we want to add its value to
// the total
if ($(this).prop('checked')) {
// .val() returns a string, prefixing hidden_input with '+' is
// a trick to cast it as a number
total += +hidden_input;
}
console.log(id, id_number, hidden_input, total);
});
// We've processed all inputs and have a total, update our page with
// the result
$('#total').html(total);
});
Done!
The above works fine, but here are some suggestions for minor improvements:
1) Use for on your labels, so that clicking on the text will also toggle the checkbox.
2) It is good practice to cache your jQuery selectors, otherwise jQuery has to parse the DOM each time to look for them. That's trivially unimportant in this example, but it is good practice to get into so you won't get bitten by problems as your pages get more complex.
3) It is good practice to separate your JS code into smaller chunks, so eg have a function that sums up the price, and a separate event handler which simply calls that when an option is changed.
Putting all that together, here's updated code:
<!-- Just one for example -->
<div>
<input type="checkbox" class="option" id="option_1" name="option_1" value="1" checked>
<input type="hidden" value="1" class="option_price_1">
<label for="option_1">Orange</label>
<label>1</label>
</div>
And now the JS:
// Cache your selectors
var $options = $('.option'),
$total = $('#total');
// Event handler, with callable function
$options.on('change', sumInputs);
function sumInputs() {
var id, id_number, hidden_input, price = 0;
$options.each(function(index) {
id = $(this).attr('id');
id_number = id.split("_")[1];
hidden_input = $(".option_price_" + id_number).val();
if ($(this).prop('checked')) {
price += +hidden_input;
}
console.log(id, id_number, hidden_input, price);
});
$total.html(price);
}

how do I check dynamically generated radio input value

I have to generate multiple input fields dynamically for each time user clicks "add" button and I was successfully able to get them. Each contact should have this radio input field in different different name so I've created a name in an array form.
Here's what I have so far and I wonder how I'm supposed to get the radio value for each person:
var options = '';
var count = 0;
var maxfields = 4;
$('button#add').click(function() {
options = '<p>Visit Type:
<label class="radio-inline">
<input type="radio" class="c_visittype' + count +'" name="c_visittype[]" value="Student" required>Student</label>
<label class="radio-inline">
<input type="radio" class="c_visittype' + count +'" name="c_visittype[]" value="Visitor" required>Visitor</label> </p>';
if(count < maxfields){
count++;
$(options).fadeIn("slow").appendTo('.companion');
return false;
}
});
$('.c_visittype' + count).on('click', function(){
$('input:radio[name="c_visittype"]').attr('checked', 'checked');
});
Each person should get a choice of either 'student' or 'visitor' and I have to get this value for multiple persons whenever more person fields created.The reason why I put field's name as an array is to iterate it in the next page by php.
<script src="http://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
<script>
$( document ).ready(function() {
var options = '';
var count = 0;
var maxfields = 4;
$('button#add').click(function() {
var options = '<p style="display: none">Visit Type:<label class="radio-inline"> <input type="radio" class="c_visittype' + count +'" name="c_visittype' + count +'[]" value="Student" required>Student</label> <label class="radio-inline"><input type="radio" class="c_visittype' + count +'" name="c_visittype' + count +'[]" value="Visitor" required>Visitor</label> </p>';
if(count < maxfields){
count++;
$('.companion').append(options);
$(".companion p:last").fadeIn();
}
});
});
</script>
<button id="add">add</button>
<div class="companion">
</div>
$('input[name=c_visittype[]]:checked').val();
That's how you access the value of a checked radio button with jQuery.
var inputValues = [];
$('.c_visittype:checked').each(function() {
inputValues.push($(this).val());
});
// Your code using inputValues
For update on changes:
$(function() {
$('.c_visittype').click(function(){
// Insert code here
}
)});
Make sure to move the numbering from the class attribute to the name attribute (like it was, everything was part of the same set of options). Also, put the whole string on 1 line.

How to keep values of radio elements

SOLVED:
I am using jQuery to allow a user to dynamically add fields to a form and I am requiring that they select certain yes and no values. When I clone the row I need to keep the values on input radio elements but not on the text element. I was expecting that this would do it but no luck.
How would I keep the values on the radio elements?
Also when the previous node has radios selected the cloning duplicates the selection information. I DON'T want that to happen.
HTML:
<div class="dynamic-node">
<input type="text" name="custom-name[0]" value=""/>
<hr>
<input type="radio" name="haswood[0]" value="yes"/>Yes
<input type="radio" name="haswood[0]" value="no"/>No
<hr>
<input type="radio" name="hasmetal[0]" value="yes"/>Yes
<input type="radio" name="hasmetal[0]" value="no"/>No
<hr>
<input type="radio" name="hasplastic[0]" value="yes"/>Yes
<input type="radio" name="hasplastic[0]" value="no"/>No
</div>
<div class="clone-node">Add Row</div>
JQuery:
$cloneNode = $( ".clone-node" );
$cloneNode.click(function(){
var $newNode = $(".dynamic-node:last").clone(true);
$newNode.find('input').each(function() {
var $this = $(this);
$this.attr('name', $this.attr('name').replace(/\[(\d+)\]/, function($0, $1) {
return '[' + (+$1 + 1) + ']';
}));
$this.val('');
});
$newNode.insertAfter('.dynamic-node:last');
});
Solution:
Thanks to commenters below and borrowing their fresh set of eyes I resolved this by extending the code a little and making adjustment to elements based on their type and my needs:
$cloneNode = $( ".clone-node" );
$cloneNode.click(function(){
var $newNode = $(".dynamic-node:last").clone(true);
$newNode.find('input').each(function() {
var $this = $(this);
$this.attr('name', $this.attr('name').replace(/\[(\d+)\]/, function($0, $1) {
return '[' + (+$1 + 1) + ']';
}));
if( $this.is('input:text') ) {
$this.val('');
}
if( $this.is('input:radio') ) {
$this.prop('checked', false);
}
});
$newNode.insertAfter('.dynamic-node:last');
});

Stop checking checkboxes after a number of checkboxes have been checked in jQuery or JavaScript

I want to stop the user to check another checkbox after a certain number of checkboxes have been checked already. i.e. After 3 checkboxes are checked, the user cannot check anymore and a message says 'You're not allowed to choose more than 3 boxes.'
I'm almost there but the last checkbox is still being checked and I don't want that, I want it to be unchecked with the message appearing.
How do I do that:
var productList = $('.prod-list'),
checkBox = productList.find('input[type="checkbox"]'),
compareList = $('.compare-list ul');
productList.delegate('input[type="checkbox"]', 'click', function () {
var thisElem = $(this),
thisData = thisElem.data('compare'),
thisImg = thisElem.closest('li').find('img'),
thisImgSrc = thisImg.attr('src'),
thisImgAlt = thisImg.attr('alt');
if (thisElem.is(':checked')) {
if ($('input:checked').length < 4) {
compareList.append('<li data-comparing="' + thisData + '"><img src="' + thisImgSrc + '" alt="'+ thisImgAlt +'" /><li>');
} else {
$('input:checked').eq(2).attr('checked', false);
alert('You\'re not allowed to choose more than 3 boxes');
}
} else {
var compareListItem = compareList.find('li');
for (var i = 0, max = compareListItem.length; i < max; i++) {
var thisCompItem = $(compareListItem[i]),
comparingData = thisCompItem.data('comparing');
if (thisData === comparingData) {
thisCompItem.remove();
}
}
}
});
I might have misunderstood the question... see my comment.
Too prevent the selection, you can call event.preventDefault() and define the handler with the event parameter.
$('input[type="checkbox"]').click(function(event) {
if (this.checked && $('input:checked').length > 3) {
event.preventDefault();
alert('You\'re not allowed to choose more than 3 boxes');
}
});
DEMO
Alternatively, set this.checked to false. This will even prevent the browser from rendering the checkmark.
DEMO
one single jquery function for multiple forms
<form>
<input type="checkbox" name="seg"><br>
<input type="checkbox" name="seg" ><br>
<input type="checkbox" name="seg"><br>
<input type="checkbox" name="seg"><br>
</form>
<br><br><br><br><br>
<form>
<input type="checkbox" name="seg1"><br>
<input type="checkbox" name="seg1" ><br>
<input type="checkbox" name="seg1"><br>
<input type="checkbox" name="seg1"><br>
</form>
$('input[type="checkbox"]').click(function(event) {
if ($("input[name= "+ this.name +"]:checked").length > 3) {
event.preventDefault();
alert('You\'re not allowed to choose more than 3 boxes');
}
});

Categories