Display the Sum of multi select checkboxes in a texfield in jQuery - javascript

In my laravel application I have set of checkboxes inside a form.
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Test List :</strong>
<br>
#foreach($ttype as $value)
<script type="text/javascript">
jQuery(function () {
var boxId='<?php echo''.$value->id.''; ?>';
var boxPrice='<?php echo''.$value->test_desc.''; ?>';
var sum=0;
jQuery("#cbox"+boxId).click(function () {
if (jQuery(this).is(":checked")) {
sum = sum + parseInt(boxPrice);
jQuery('#msg').val(sum);
} else {
jQuery("#text").hide();
}
});
});
</script>
<label>{{ Form::checkbox('samp_list[]', $value->test_name, false, array('class' => 'name','sumT'=>''.$value->test_desc.'','id'=>'cbox'.$value->id.'')) }}
{{ $value->test_name }}</label>
<br/>
#endforeach
</div>
</div>
Each checkbox has its own value called charge, Eg: for checkbox 1 the charge is 450, checkbox 2, it's 1000.... for the 10th check box charge is 2300...
Now when every time when a user selects a checkbox I'm trying to display the sum of those selected checkboxes in a text field.
{!! Form::text('samp_charges', null, array('placeholder' => 'Registration Charges','class' => 'form-control','id'=>'msg')) !!}
But My issue is, whenever I select more than 1 option it does not display the sum. Instead, it gives me the value of the last selected check box.
How can I display the sum of all selected checkboxes in that text field and once I unselect a checkbox, substract that value from the sum

Use class and data attribute - in plain HTML/PHP it would look like
<input class="cbox" type="checkbox" data-price="<?= $boxprice ?>" />
Delegate:
$(function() {
$(".cbox").on("change", function() {
const vals = $(".cbox:checked")
.map(function() {
return +this.dataset.price
})
.get();
// test we have an array of values
const sum = vals.length>0 ? vals.reduce((a, b) => a + b) : 0; // if no, zero sum
$('#msg').val(sum)
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
100: <input class="cbox" type="checkbox" data-price="100" /><br/> 200: <input class="cbox" type="checkbox" data-price="200" /><br/> 300: <input class="cbox" type="checkbox" data-price="300" /><br/>
<input type="text" readonly id="msg" />
If you do not like to use class class, then use $("[id^=cbox]") instead of $(".cbox")

Related

Disallowing to select already selected value in combobox using JQUERY

Hi I have the following code for appending comboboxes when button is clicked.
I want to check if the value is selected in any previous combobox if it is selected then alert "value is already selected".
For example, I have 5 comboboxes appended and the value in each combobox should be different from each other by traversing each value in the comboboxes:
<div class="custom-control custom-checkbox">
<input type="checkbox" class="itemRow custom-control-input" id="itemRow_1">
<label class="custom-control-label" for="itemRow_1"></label>
</div>
<div class="form-group has-success">
<select name="proid[]" class="form-control" id="proid_1" required="required">
</select>
</div>
<div class="form-group has-success">
<button type="button" name="addbtn" id="addbtn" class="btn btn-success">Add Product</button>
</div>
JQUERY CODE
var count = $(".itemRow").length;
$(document).on('click', '#addbtn', function() {
count++;
var productcombo='';
productcombo += '<tr>';
productcombo +='<td><input type="checkbox" class="custom-control-input itemRow" id="itemRow_'+count+'"> <label class="custom-control-label" for="itemRow_'+count+'"></label> </td>';
productcombo +='<td><select name="proid[]" class="form-control" id="proid_'+count+'" required="required"> </select></td>';
productcombo += '</tr>';
$('#products').append(productcombo);
});
$("#proid_"+count).change(function()
{
var id = $(this).find(":selected").val();
// code here to compare each value
if(value found in previous comboboxes)
{
alert("Already Selected");
}
});
You can set an array variable and when user select a value of combobox, push the value in it.
var selectedVals = [];
$("#proid_"+count).change(function() {
var id = $(this).find(":selected").val();
// code here to compare each value
if(selectedVals.includes(id)) {
alert("Already Selected");
} else {
selectedVals.push(id);
}
});

How to post multiple appended input field values via ajax

So, I've been trying to provide a user interface in an html page whereby the user can type a number in an input field and hit apply (using addRowsForm), to see rows of various input fields being appended to another separate form (named createRecordForm) and later submit this form (including all those appended inputs and two other hidden fields) via ajax.
My problem is that I cannot find a way to group the data and post it due to the unpredictable number of input fields that would be added, depending on the user's interaction with the page. Your help is greatly appreciated.
Here are my codes:
addRowsForm
<form action="#" name="addRowsForm" id="addRowsForm" method="post">
<div class="form-group">
<input type="number" min="1" max="10" name="addRowCounter" id="addRowCounter">
</div>
<button type="submit" name="applyBtn" id="applyBtn">Apply</button>
</form>
createRecordForm
<table class="table table-bordered table-striped table-sm">
<thead class="bg-brand-4th-color">
<th>Link Type</th>
<th>Link</th>
<th>Recorded Time</th>
<th>Video Visibility</th>
</thead>
<form action="" method="POST" name="createRecordForm" id="createRecordForm">
<input type="hidden" name="ats_id" value="{{atsIdForFrag}}">
<input type="hidden" name="tot_rows" value="">
<tbody id="tBody">
</tbody>
<tfoot>
{# submit btn #}
<tr>
<td colspan="4">
<div class="form-group">
<button class="btn btn-success" type="submit" name="create_recorded_session_btn" id="create_recorded_session_btn">Create</button>
</div>
</td>
</tr>
</tfoot>
</form>
</table>
Javascript part:
<script>
$( document ).ready(
function(){
$("#addRowsForm").on("submit", function(e) {
e.preventDefault();
var rowCounter = $("input[name=addRowCounter]").val();
$("input[name=tot_rows]").val(rowCounter);
//reset any previous content
$("#tBody").html('');
for (var i = 1; i <= rowCounter; i++)
{
var newRowContent =
"<tr><td><div class='form-group p-0 m-0'><select class='form-control' name='link_type_row_"+i+"' required><option value='google_drive' selected>Google Drive</option></select></div></td><td><div class='form-group p-0 m-0'><input class='form-control' type='text' name='link_row_"+i+"' value='' required></div></td><td><div class='form-group p-0 m-0'><input type='datetime-local' name='datetime_row_"+i+"' class='form-control' required/></div></td><td><div class='form-check'><input class='form-check-input' type='radio' name='visibilityRadio_row_"+i+"' id='showOption_row_"+i+"' value='show'><label class='form-check-label' for='showOption_row_"+i+"'>Show to student</label></div><div class='form-check'><input class='form-check-input' type='radio' name='visibilityRadio_row_"+i+"' id='dontShow_row_"+i+"' value='dont_show'><label class='form-check-label' for='dontShow_row_"+i+"'>Don\'t show to student</label></div></td></tr>";
$("#tBody").append(newRowContent);
}
$("#createRecordForm").on("submit", function(e) {
e.preventDefault();
var ats_id = $("input[name=ats_id]").val();
var tot_rows = $("input[name=tot_rows]").val();
// here is my broblem, I need to change this hard-coded lines into dynamic data and process it in php
var link_type_row_1 = $("select[name=link_type_row_1]").val();
var link_row_1 = $("input[name=link_row_1]").val();
var datetime_row_1 = $("input[name=datetime_row_1]").val();
var visibilityRadio_row_1 = $("input[name=visibilityRadio_row_1]:checked").val();
var link_type_row_2 = $("select[name=link_type_row_2]").val();
var link_row_2 = $("input[name=link_row_2]").val();
var datetime_row_2 = $("input[name=datetime_row_2]").val();
var visibilityRadio_row_2 = $("input[name=visibilityRadio_row_2]:checked").val();
var url = "{{ path('ao__frg_persist_st_rec_session')|escape('js') }}";
var type = "POST";
$.ajax({
url : url,
type: type,
data : {
'ats_id': ats_id,
'tot_rows': tot_rows,
'link_type_row_1': link_type_row_1,
'link_row_1': link_row_1,
'datetime_row_1': datetime_row_1,
'visibilityRadio_row_1': visibilityRadio_row_1,
'link_type_row_2': link_type_row_2,
'link_row_2': link_row_2,
'datetime_row_2': datetime_row_2,
'visibilityRadio_row_2': visibilityRadio_row_2
},
success: function(returnedMsg) {
// do something
}
});
});
});
});
</script>
[UPDATE : Check my answer below this paragraph]
If I implement the batch approach as suggested by #Kinglish, I will end up having a big single radio while each row should have its own radio input separately from the rest.
[SOLUTION TO THE UPDATE ISSUE ABOVE]
So I used the loop index number to remain the unique name and ID for each row's radio inputs. Now the row 1 has input name/id of visibilityRadio_row_1 and 2nd row's name/id is visibilityRadio_row_2. Then I used the ^ wildcard selector and the :checked property to target the value of the checked radio in each row independent of other rows.
let obj = [];
$('.data-group').each(function() {
obj.push({
link_type: $(this).find('select[name="link_type_row"]').val(),
link: $(this).find('input[name="link_row"]').val(),
created_at: $(this).find('input[name="datetime_row"]').val(),
is_active: $(this).find('input[name^="visibilityRadio_row"]:checked').val()
})
})
I would approach this differently. Consider that you can process these in batches, rather than a finite loop. Without rewriting your script, look at how these are processed. you end up with an array of objects that appear in the order they are in your form. This does away with the messy bit of appending a number to each field. In your remote script that receieves these, you can just iterate through them and, if desired, add the number at that point.
$(document).ready(function() {
$('.submit').click(function() {
let obj = [];
$('.data-group').each(function() {
obj.push({
name: $(this).find('input[name="name"]').val(),
gender: $(this).find('select[name="gender"]').val(),
favorite_color: $(this).find('input[name="favorite_color"]').val()
})
})
console.log('obj:', obj);
})
})
// I accidentally did this in vanillaJS first, so for posterity, here is that version:
/*
window.addEventListener('DOMContentLoaded', () => {
document.querySelector('.submit').addEventListener('click', () => {
let obj = [];
document.querySelectorAll('.data-group').forEach(e => {
obj.push({
name: e.querySelector('input[name="name"]').value,
gender: e.querySelector('select[name="gender"]').value,
favorite_color: e.querySelector('input[name="favorite_color"]').value
})
})
console.log('obj:', obj);
})
})
*/
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='data-group'>
<input name='name' value='john' />
<select name='gender'>
<option selected value='this'>this</option>
<option value='that'>that</option>
<option value='other'>other</option>
</select>
<input name='favorite_color' value='blue' />
</div>
<div class='data-group'>
<input name='name' value='mary' />
<select name='gender'>
<option value='this'>this</option>
<option value='that' selected>that</option>
<option value='other'>other</option>
</select>
<input name='favorite_color' value='green' />
</div>
<hr>
<button class='submit'>click</button>

How to change the value of a previous check box that has been selected in JQuery?

Here is what I'm trying to do.
I have the ability to create a form when there is an option to create one in Javascript.
Here is an option to add an address:
<i class="fas fa-plus-circle"></i> <span class="newUrlText">add new address
Here is the form in question:
<input type="text" class="form-control" id="new-address-1-%ID%" name="new-address-1-%ID%" placeholder="Address Line 1">
<input type="text" class="form-control" id="new-address-2-%ID%" name="new-address-2-%ID%"
placeholder="Address Line 2">
<label for="message" class="control-label"><span class="billable-text"><?php _e('Primary Address'); ?></span></label>
<label class="switch" for="primary-%ID%" style="margin-left: 10px;top: 10px;">
<input type="checkbox" class="primary-%ID%" name="primary-%ID%" id="primary-%ID%" />
<div class="slider round gray"></div>
</label>
Here is the javascript that generates the form:
<script language="javascript">
var newAddressIndex = 1;
var addressarray = [];
function addNewAddress() {
var container = getElement("addressContainer");
addressarray.push(newAddressIndex);
var htmlAddress = '<?php echo addslashes(App_String::stripBreaksTabsMultipleWhitespace($newAddress)); ?>';
htmlAddress = htmlAddress.replace(/%ID%/g, newAddressIndex);
var node = document.createElement("div");
node.innerHTML = htmlAddress;
container.appendChild(node);
$('#newAddressCount_'+newAssetIndex).val(newAssetIndex);
++newAddressIndex;
test(addressarray);
}
What I'm trying to do is the following:
If the user selects the checkbox and then decides to select the next checkbox, I would like to change the previous checkbox from selected to no selected.
How would I go about doing that?
Thank you
I found a solution:
What I did was, that I created a function to get the current value of the checkboxes like this:
getAddrValue(addressarray);
Then within the function the follwoing:
function getAddrValue (addressarray) {
$('#primary-'+index).change(function() {
var checked = this.checked ? 1 : 0;
prevCheckbox = index-1;
if (checked == 1) {
if (document.getElementById('primary-'+prevCheckbox) !== null ) {
let inputs = document.getElementById('primary-'+prevCheckbox);
inputs.checked = false;
}
}
});
}

How can I sum multiple Numeric textbox value?

I have multiple Numeric textbox as shown below in the snippet, all are currency format textbox's. How can I sum the values of textboxes in Class Name Charges and display the total sub-total-Of-Charges textbox and subtract if any value in textbox's with class=sub from sub-total-Of-Charges textbox value.
I have used the following jQuery Code which is working but two problems.
Doesn't Keep the currency format
the value of net-invoiced-amount is updated only when I update textbox value in textbox class .sub same thing .sub-total-Of-Charges value is updated on .Charges are updated but I need to re-calculate or update the value net-invoiced-amount or .sub-total-Of-Charges whenever .sub or .charges textbox's values are changed.
$(document).ready(function () {
$(document).on("change", ".charges", function () {
var calculated_total_sum = 0;
$(".charges").each(function () {
var get_textbox_value = $(this).val();
if ($.isNumeric(get_textbox_value)) {
calculated_total_sum += parseFloat(get_textbox_value);
}
});
$(".sub-total-Of-Charges").val(calculated_total_sum);
});
$(document).on("change", ".sub", function () {
var netInvoicedAmount = $(".sub-total-Of-Charges").val();
$(".sub").each(function () {
var get_textbox_value = $(this).val();
if ($.isNumeric(get_textbox_value)) {
netInvoicedAmount -= parseFloat(get_textbox_value);
}
});
$(".net-invoiced-amount").val(netInvoicedAmount).trigger("change");
});
});
You need to get reference of textbox where you need to set the updated value using data("kendoNumericTextBox") and then set new value using .value("newwvalue") this will update new value according to the format which you have set earlier .
Also , use $(this).attr("aria-valuenow") to get the original value of textbox without any currency and change your selector to $(".k-formatted-value.charges") to get only input value from particular textbox .Currently , when you will inspect html generated it has 2 input box with same class that's the reason total sum is not working.
Demo Code :
$("#TotalDirectLaborCharges, #TotalIndirectLaborCharges, #TotalContractCharges, #TotalTravelCharges, #TotalAdjustments, #TotalAdjustments, #CostsAlreadyPaid, #Other, #NetInvoicedAmount ,#SubtotalOfCharges").kendoNumericTextBox({
decimals: 2,
format: "c"
});
//add both selector
$(document).on("change", ".charges,.sub", function() {
var calculated_total_sum = 0;
$(".k-formatted-value.charges").each(function() {
//get original value without currecny
var get_textbox_value = $(this).attr("aria-valuenow");
if ($.isNumeric(get_textbox_value)) {
calculated_total_sum += parseFloat(get_textbox_value);
}
});
//get kendo textbox
var numerictextbox = $("#SubtotalOfCharges").data("kendoNumericTextBox");
//set value
numerictextbox.value(calculated_total_sum);
});
//add both selector
$(document).on("change", ".sub ,.charges", function() {
//get value from inputbox
var netInvoicedAmount = $("#SubtotalOfCharges").data("kendoNumericTextBox").value();
$(".k-formatted-value.sub").each(function() {
//get original value
var get_textbox_value = $(this).attr("aria-valuenow");
if ($.isNumeric(get_textbox_value)) {
netInvoicedAmount -= parseFloat(get_textbox_value);
}
});
//set value in invoice amt
var numerictextbox = $("#NetInvoicedAmount").data("kendoNumericTextBox");
numerictextbox.value(netInvoicedAmount);
});
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.3.1021/styles/kendo.common.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.3.1021/styles/kendo.rtl.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.3.1021/styles/kendo.default.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.3.1021/styles/kendo.mobile.all.min.css">
<script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2020.3.1021/js/angular.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2020.3.1021/js/jszip.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2020.3.1021/js/kendo.all.min.js"></script>
<div class="quarter m-l-lg m-y text-right">
<label class="m-r-lg required" asp-for="TotalDirectLaborCharges">Total Direct Labor Charge<br /></label>
<input id="TotalDirectLaborCharges" class="charges" /><br />
<label class="m-r-lg required" asp-for="TotalIndirectLaborCharges">TotalIndirectLaborCharges<br /></label><br />
<input id="TotalIndirectLaborCharges" class="charges" /><br />
<label class="m-r-lg required" asp-for="TotalContractCharges">TotalContractCharges</label><br />
<input id="TotalContractCharges" class="charges" /><br />
<label class="m-r-lg required" asp-for="TotalTravelCharges">TotalTravelCharges</label><br />
<input id="TotalTravelCharges" class="charges" /><br />
<label class="m-r-lg required" asp-for="TotalAdjustments">TotalAdjustments</label><br />
<input id="TotalAdjustments" class="sub" /><br />
<label class="m-r-lg required" asp-for="CostsAlreadyPaid">CostsAlreadyPaid</label><br />
<input id="CostsAlreadyPaid" class="sub" /><br />
<label class="m-r-lg required" asp-for="Other">Other</label><br />
<input id="Other" class="sub" /><br />
<label class="m-r-lg required" asp-for="SubtotalOfCharges">SubtotalOfCharges</label><br />
<input id="SubtotalOfCharges" readonly class="sub-total-Of-Charges" />
<br />
<label class="m-r-lg required" asp-for="Other">NetInvoicedAmount</label><br />
<input id="NetInvoicedAmount" readonly class="netInvoicedAmount" />
</div>
As you've used jQuery for your project, I'm also writing this answer using the library.
$(document).ready(function() {
let $references = {
subtotal: $('#SubtotalOfCharges').first(),
net: $('#NetInvoicedAmount').first(),
fields: {
subtract: $('input.sub'),
charge: $('input.charges')
}
}
function calculateSum($elements) {
return Array.from($elements).reduce((previousValue, element) => {
val = $(element).val();
if(val)
previousValue += parseFloat($(element).val());
return previousValue;
}, 0)
}
$(document).on('change', 'input', function() {
let sum = {
subtract: calculateSum($references.fields.subtract),
charge: calculateSum($references.fields.charge),
}
$references.subtotal.val(sum.charge);
$references.net.val(sum.charge - sum.subtract);
});
})
input,
label {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label>Total Direct Labor Charge</label>
<input id="TotalDirectLaborCharges" class="charges">
<label>TotalIndirectLaborCharges</label>
<input id="TotalIndirectLaborCharges" class="charges">
<label>TotalContractCharges</label>
<input id="TotalContractCharges" class="charges">
<label>TotalTravelCharges</label>
<input id="TotalTravelCharges" class="charges">
<label>TotalAdjustments</label>
<input id="TotalAdjustments" class="sub">
<label>CostsAlreadyPaid</label>
<input id="CostsAlreadyPaid" class="sub">
<label>Other</label>
<input id="Other" class="sub">
<label>SubtotalOfCharges</label>
<input id="SubtotalOfCharges" readonly class="sub-total-Of-Charges">
<label>NetInvoicedAmount</label>
<input id="NetInvoicedAmount" readonly class="net-invoiced-amount">
How does it work?
Instead of manually triggering a change event whenever a .sub (or .charges) is changed, to calculate the subtotal/net amount, you can bind the event handler to both of the input groups and run the calculations once.
I've used $references to tidy up the code a little bit and a reduce function is used to calculate the sum of a field group.
Array.from is used to create a native Javascript array from the jQuery object.
For more information on Array.reduce, visit its documentation here, and for more information on Array.from visit here.
Finally, a feasible solution is to use input prefixes. Every UI framework normally has one built-in, otherwise, you can take a look at Bootstrap's input groups here (Especially, .input-group-prepend).

select option display input block and enter value that count and display another inptut value auto

I have a HTML form that is for payment status in my panel. In this form if i select payment status Advance Paid Then displays The another input box that i can enter for the advanced paid price. There is another input box is available that is remaining price if i entered the value of advance paid the remaining price should be display the remaining value using java script. If I choose payment status is Null then display total price in remaining price input box and if i choose Paid then display 0 in remaining price input box...all things run good ...but only one thing is not working that is if i enter the value of advance price the remaining price is not displyed. Here is my HTML Code
<div class="col-md-6">
<div class="form-group">
<label>Final Total</label>
<input type="text" value="100" name="total" id="Ftotal" class="form-control" >
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="paymentstatus">Payment Status</label>
<select class="form-control" name="paymentstatus" style="height: 40px;" onchange="yesnoCheck(this);">
<option value=""> ---Select Payment Status---</option>
<option>Advance</option>
<option>Null</option>
<option>Paid</option>
</select>
</div>
</div>
<div class="col-md-6" id="ifYes" style="display: none;">
<div class="form-group">
<label for="advancepaid">Advanced Paid</label>
<input type="text" name="advancedPiad" id="advancedPiad" onKeyUp="remaining()" class="form-control">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="remainingammount">Remaining Ammount</label>
<input type="text" name="remaining" id="remaining" class="form-control remaining" >
</div>
</div>
this is my javascript
function yesnoCheck(that) {
if (that.value == "Advance") {
document.getElementById("ifYes").style.display = "block";
} else {
document.getElementById("ifYes").style.display = "none";
}
if (that.value == "Null") {
a = Number(document.getElementById('Ftotal').value);
document.getElementById('remaining').value = a;
}
if (that.value == "Paid") {
a = 0;
document.getElementById('remaining').value = a;
}
}
function remaining()
{
a = Number(document.getElementById('Ftotal').value);
b = Number(document.getElementById('advancedPiad').value);
c = a - b;
document.getElementsByClassName("remaining").value = c;
}
Try
document.getElementsByClassName("remaining")[0].value = c;
document.getElementsByClassName gives you the array of the elements with the class name specified. In your case just set the value of first element.
Try to use js parseInt() method to convert it into integer
function remaining()
{
a=parseInt(document.getElementById('Ftotal').value);
b = parseInt(document.getElementById('advancedPiad').value);
c = a - b;
document.getElementsByClassName("remaining").value = c;
}

Categories