How do I dynamically sum input values inside a repeatable fields? - javascript

How can i get total of dynamically created each fields value
<div class="rf-row count-container">
<input class="total">
<div class="row">
<input class="add-monthly">
</div>
<div class="row">
<input class="add-monthly">
</div>
<div class="row">
<input class="add-monthly">
</div>
</div>

Please check this code this may help
<!DOCTYPE html>
<html>
<head>
Demo
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<div class="rf-row count-container">
<input class="total">
<div class="row">
<input class="add-monthly" value="5">
</div>
<div class="row">
<input class="add-monthly" value="5">
</div>
<div class="row">
<input class="add-monthly" value="5">
</div>
</div>
<script>
$(document).ready(function(){
var value = 0;
$('.count-container .row').each(function(){
value += parseInt($(this).find('.add-monthly').val()) ? parseInt($(this).find('.add-monthly').val()) : 0
})
$('.total').val(value);
});
</script>
</body>
</html>
check below link
https://codepen.io/anon/pen/gdpZpR?editors=1010

Since you have jquery tagged, the following is the way you'd iterate over all your inputs of class add-monthly and sum their values together, finally returning the sum value:
function sumFields() {
var totalSum = 0;
$("input.add-monthly").each(function () {
totalSum += $(this).val();
});
return totalSum;
}

If you are dynamically adding input fields, I would suggest delegating the change functionality to the parent .count-container. Once the event is triggered, I am iterating over the .add-monthly fields to sum up their values. To help JavaScript understand that these values are floats (since I assume we are dealing with a currency), I am using parseFloat() to insure the value can be added to the sum. Lastly, I am setting the value of .sum-monthly to use toFixed() to format a number using a fixed-point notation (again I am assuming we are dealing with a currency).
$(document).ready(function() {
$('.count-container').on('change', '.add-monthly', function() {
let total = 0;
$('.add-monthly').each(function() {
total += parseFloat($(this).val()) || 0;
});
$('.sum-monthly').val(total.toFixed(2));
}).find('.add-monthly').change();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="rf-row count-container">
<input class="sum-monthly" readonly>
<div class="sub-rf-row">
<input class="add-monthly">
</div>
<div class="sub-rf-row">
<input class="add-monthly">
</div>
<div class="sub-rf-row template">
<input class="add-monthly">
</div>
</div>

var classes = document.getElementsByClassName('add-monthly')
classes = [...classes]
var result = classes
.map(item => +item.value)
.reduce((a, b) => a + b, 0);
document.getElementsByClassName('sum-monthly')[0].value = result
console.log('summ', result)
<div class="rf-row count-container">
SUM: <input class="sum-monthly"/><br/>
<div class="sub-rf-row">
<input class="add-monthly" type="number" value="1">
</div>
<div class="sub-rf-row">
<input class="add-monthly" type="number" value="4">
</div>
<div class="sub-rf-row template">
<input class="add-monthly" type="number" value="0">
</div>
</div>

Related

How to change the value of an Input control when the text of another Input control is changed?

I need the following output as shown in the gif below.
I created three inputs which I put in the box below. How can I have such output?
Please help with an example
NOTE:Suppose we have 50 inputs and the class is the same
I can't use it after Get ID
MY HTML code
<span class="pricing-heading">Your sale price:</span><div class="pricing-field"><input class="pricing-set-price" type="number" value="24.00"></div>
</div>
<div class="prt-pricing-detial">
<span class="pricing-heading">Product base Cost:</span><div class="pricing-field"><input class="pricing-base-price" type="number" value="10.00" disabled></div>
</div>
<div class="prt-pricing-detial">
<span class="pricing-heading">Your profit:</span><div class="pricing-field"><input class="pricing-profit" type="number" value="14.00" disabled></div>
</div>
JS code :
$(".pricing-set-price").change(function(){
var item_rrp = $(this).val();
var item_base = $(this).parent().parent().parent().find('.pricing-base-price').val();
var profit = item_rrp - item_base;
var profit_format = profit.toFixed(2);
$(this).parent().parent().parent().find('.pricing-profit').val(profit_format);
});
You may try like
$(".pricing-set-price").change(function(){
let currentValue = $(this).val();
var previousValue = this.defaultValue;
if(previousValue < currentValue){
this.defaultValue = currentValue;
console.log('Increment');
}else{
console.log('Decrement');
}
});
You can call the function that changes the value of Profit (input) on the onchange , oninput, or onClick events of the SalePrice(input)
function increment() { document.getElementById('salePrice').stepUp();
calculateProfit()
}
function decrement() {
document.getElementById('salePrice').stepDown();
calculateProfit()
}
function calculateProfit(){
let sp = document.getElementById("salePrice").value;
document.getElementById("profit").value = sp - 10;
}
<input id="salePrice" type=number value=10 min=10 max=110 />
<button onclick="increment()">+</button>
<button onclick="decrement()">-</button>
<br/>
Base Price :: <input type="text" id="basePrice" value=10
disabled >
<br/>
Profit :: <input type="text" id="profit" value=0 />
For more info about:
stepUp()
https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/stepUp
stepDown()
https://www.w3schools.com/Jsref/met_week_stepdown.asp
Hi i think this might help. use id for your input fields.
function calculateProfit(val){
var baseCost = document.getElementById("baseCost").value;
document.getElementById("Profit").value = (val - baseCost).toFixed(2);
}
<div class="prt-pricing-heading">
<span class="pricing-heading">Your sale price:</span>
<div class="pricing-field"><input id="SalePrice" class="pricing-set-price" type="number" value="24.00" onchange="calculateProfit(this.value);" oninput="calculateProfit(this.value)"></div>
</div>
<div class="prt-pricing-detial">
<span class="pricing-heading">Product base Cost:</span>
<div class="pricing-field"><input id="baseCost" class="pricing-base-price" type="number" value="10.00" disabled></div>
</div>
<div class="prt-pricing-detial">
<span class="pricing-heading">Your profit:</span>
<div class="pricing-field"><input id="Profit" class="pricing-profit" type="number" value="14.00" disabled></div>
</div>
For More info regarding:
oninput() https://www.w3schools.com/tags/att_oninput.asp
onchange() https://www.w3schools.com/tags/ev_onchange.asp

adding click events to divs to change hidden input values

I am trying to get two divs to act as checkboxes (so that users can select 0 or all) that will influence hidden input values for a total that starts at 0. I am targetting the clicked divs by toggling a bootstrap color class to show user which has been chosen and - based on that class - add values to the hidden total input values below. I can get the totals to change outright, but I am trying to add to and subtract from the totals based on what is clicked/unclicked. Right now my code is returning an "Uncaught TypeError: Cannot set property 'value' of null". Any help you can give will be greatly appreciated!
$(document).ready(function() {
$('.select-class').on('click', function() {
//toggle clicked divs to show what's been selected
$(this).toggleClass('color');
//add values to total(0) if divs are clicked (have color class)
if (this.classList.contains('color')) {
//add1:
var addTotal1 = Number(document.getElementsByName('total1').value);
var addSingle1 = Number(document.getElementById(this.id.toString() + 'add1').value);
addTotal1 += addSingle1;
document.getElementById('totaladd1').value = addTotal1.toString();
//add2:
var addTotal2 = Number(document.getElementsByName('total2').value);
var addSingle2 = Number(document.getElementById(this.id.toString() + 'add2').value);
addTotal2 += addSingle2;
document.getElementById('totaladd2').value = addTotal2.toString();
//add3:
var addTotal3 = Number(document.getElementsByName('total3').value);
var addSingle3 = Number(document.getElementById(this.id.toString() + 'add3').value);
addTotal3 += addSingle3;
document.getElementById('totaladd3').value = addTotal3.toString();
}
//Subtract values if divs are unclicked (don't have color class)
if (!this.classList.contains('color')) {
//add1:
var addTotal1 = Number(document.getElementsByName('total1').value);
var addSingle1 = Number(document.getElementById(this.id.toString() + 'add1').value);
addTotal1 -= addSingle1;
document.getElementById('totaladd1').value = addTotal1.toString();
//add2:
var addTotal2 = Number(document.getElementsByName('total2').value);
var addSingle2 = Number(document.getElementById(this.id.toString() + 'add2').value);
addTotal2 -= addSingle2;
document.getElementById('totaladd2').value = addTotal2.toString();
//add3:
var addTotal3 = Number(document.getElementsByName('total3').value);
var addSingle3 = Number(document.getElementById(this.id.toString() + 'add3').value);
addTotal3 -= addSingle3;
document.getElementById('totaladd3').value = addTotal3.toString();
}
})
});
<div class="row p-lg-5">
<div id="div1" class="select-class">
<p>Content</p>
<!--hidden values-->
<div class="d-none">
<input type="number" class="add1" id="div1add1" value="1" />
<input type="number" class="add2" id="div1add2" value="45" />
<input type="number" class="add3" id="div1add3" value="4" />
</div>
</div>
<div id="div2" class="select-class">
<p>Content</p>
<!--hidden values-->
<div class="d-none">
<input type="number" class="add1" id="div2add1" value="3" />
<input type="number" class="add2" id="div2add2" value="20" />
<input type="number" class="add3" id="div2add3" value="3" />
</div>
</div>
</div>
<!--hidden totals-->
<div class="d-none">
<input id="totaladd1" type="number" name="total1" value="0" />
<input id="totaladd2" type="number" name="total2" value="0" />
<input id="totaladd3" type="number" name="total3" value="0" />
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Set your add inputs as disabled by default
Add a data-total="" to every total input. Inside the data place the add-inputs-pairs selector i.e: ".add_1" etc...
Toggle class on click and perform a search for the non disabled add inputs, reducing their values to an accumulated number. Set that number as the iterating total input value
jQuery(function($) {
function calculateTot() {
$('[data-total]').each(function() {
const pair = $(this.dataset.total).not(':disabled').get();
$(this).val(pair.reduce((n, el) => (n += +el.value, n), 0))
});
}
$('.select-class').on('click', function() {
$(this).toggleClass('is-selected');
$(this).find('input').prop('disabled', !$(this).is('.is-selected'));
calculateTot();
}).find('input').prop('disabled', true); // Make inputs disabled by default
calculateTot(); // Calculate also on DOM ready
});
.select-class {cursor:pointer; padding:8px; border-radius:1em; border:1px solid #000;}
.is-selected {background:#0bf;}
.d-none {display:none;}
<div class="row p-lg-5">
<div id="div1" class="select-class">
Content 1 - Select me
<div class="d-none">
<input type="number" class="add_1" value="1" />
<input type="number" class="add_2" value="45" />
<input type="number" class="add_3" value="4" />
</div>
</div>
<div id="div2" class="select-class">
Content 2 - Select me
<div class="d-none">
<input type="number" class="add_1" value="3" />
<input type="number" class="add_2" value="20" />
<input type="number" class="add_3" value="3" />
</div>
</div>
</div>
<div> <!-- class="d-none" -->
<input data-total=".add_1" type="number" name="total1" />
<input data-total=".add_2" type="number" name="total2" />
<input data-total=".add_3" type="number" name="total3" />
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

How can I validate multiple grouped inputs?

I've this structure here:
<div>
<div class="row">
<input id="1a">
<input id="1b">
</div>
<div class="row">
<input id="2a">
<input id="2b">
</div>
<div class="row">
<input id="3a">
<input id="3b">
</div>
<div class="row">
<input id="4a">
<input id="4b">
</div>
</div>
If the user leaves everything empty, there is no problem. But when he enters for example something into 1a and leaves 1b empty, this should cause an error. So how can I find out if a & b is filled for each row? It's a bit tricky and I have no idea how to deal with this.
You can achieve it in this simple way
$('button').on("click", () => {
$('body').find(".row").each(function(index, row){
var count = 0;
$(row).find("input").each(function(i, input) {
if($(input).val() !== "")
count++;
})
if(count === 1)
alert("Row " + (index + 1) + " is invalid");
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<div class="row">
<input id="1a">
<input id="1b">
</div>
<div class="row">
<input id="2a">
<input id="2b">
</div>
<div class="row">
<input id="3a">
<input id="3b">
</div>
<div class="row">
<input id="4a">
<input id="4b">
</div>
</div>
<button>Check</button>
something like that ?
const inRow = document.querySelectorAll('.row')
, valida = document.querySelector('button')
, respon = document.querySelector('output')
;
valida.onclick =_=>
{
let OK = true
inRow.forEach(eR=>
{
let vals = 0
eR.querySelectorAll('input').forEach(eI=>{ vals+=eI.value.length ? 1:0 })
if (vals===1) OK=false
})
respon.value = OK ? 'OK' : 'bad'
}
<div>
<div class="row"> <input id="1a"> <input id="1b"> </div>
<div class="row"> <input id="2a"> <input id="2b"> </div>
<div class="row"> <input id="3a"> <input id="3b"> </div>
<div class="row"> <input id="4a"> <input id="4b"> </div>
</div>
<button>validate</button> <output></output>
Normally multiple form controls (ex <input>, <textarea>, <select>, etc) should be inside a <form> tag. Moreover, the behavior described is called form validation which requires said <form> tag to be triggered by a "submit" event.
The following demo features proper HTML
<form> and <fieldset> instead of <div>
added <output> for each <fieldset>
Also the JavaScript is designed to show a message when any pair of <input> has a .value and the other doesn't.
The message: <output>Complete data input</output>
This pseudo-form validation is triggered whenever a user enters data within an <input> and then clicks (aka "blur" event). This entire chain of actions combined is the "change" event.
The <form> tag is registered to the "change" event so if any of the <input> within the <form> is the event origin (aka event.target - the <input> that the user triggers a "change" event on).
const form = document.forms[0];
form.onchange = reqData;
function reqData(event) {
let origin = event.target;
if (origin.tagName === 'INPUT') {
const parent = origin.parentElement;
const output = parent.querySelector('output');
const inputs = [...parent.querySelectorAll('input')];
let total = inputs.length;
let count = 0;
for (let input of inputs) {
if (input.value) {
count++;
}
}
if (count < total && count > 0) {
output.style.opacity = '1';
} else {
output.style.opacity = '0';
}
}
return false;
}
output {
opacity: 0;
color: tomato
}
<form>
<fieldset>
<input><br>
<input> <output>Complete data input</output>
</fieldset>
<fieldset>
<input><br>
<input> <output>Complete data input</output>
</fieldset>
<fieldset>
<input><br>
<input> <output>Complete data input</output>
</fieldset>
<fieldset>
<input><br>
<input> <output>Complete data input</output>
</fieldset>
</form>

HTML Form - similar input groups as an array of objects

So I have a form with two identical group of inputs that represent education info. There could be more than two as I want to include a button to create a new group so the user can put all his education background like in LinkedIn.
<form id="formCV" action="">
<div id="educationContainer">
<!-- First Group -->
<div class="education">
<div>
<input type="text" name="institutionName">
</div>
<div>
<input type="text" name="courseName">
</div>
<div>
<input type="month" name="startDate">
</div>
<div>
<input type="month" name="endDate">
</div>
</div>
<!-- Second Group -->
<div class="education">
<div>
<input type="text" name="institutionName">
</div>
<div>
<input type="text" name="courseName">
</div>
<div>
<input type="month" name="startDate">
</div>
<div>
<input type="month" name="endDate">
</div>
</div>
</div>
</form>
Now, if I use the FormData API to get the form data like this:
for(let entry of formData.entries()){
console.log(entry);
}
I get the following output:
(2) ["institutionName", "Harvard"]
(2) ["courseName", "Web Development"]
(2) ["startDate", "2000-11"]
(2) ["endDate", "2008-11"]
(2) ["institutionName", "Oxford"]
(2) ["courseName", "Business Management"]
(2) ["startDate", "2009-10"]
(2) ["endDate", "2010-05"]
What I want to achieve is to get the output in an organized way, like this:
education:[
{
institutionName:"Harvard",
courseName:"Web Development",
startDate:"2000-11",
endDate:"2008-11"
},
{
...
}
]
So I'm interested in knowing the best approach to achieve this. Thanks in advance for any help!
It does not make sense to have two equal forms, with one being sufficient.
In addition to the form you should have a list that shows each item added.
It's what I recommend.
Not sure whether this is the best approach, but you can achieve the desired structure like this:
const formCV = document.querySelector('#formCV');
const formData = new FormData(formCV);
function groupEducationData(inputGroupSize = 4) {
const result = [];
let educationObj = null;
let counter = 0;
for (const entry of formData.entries()) {
// Since the counter is divisible by the number of inputs in a group
// only if one form group finishes. And when one form group finishes,
// we need to add the object into the result array
if (counter % inputGroupSize === 0) {
// if this is the first iteration, the educationObj is null and
// we don't want to add it to the result array yet
// we only add the educationObj to the result array if it is
// an object containing the education info
if (educationObj) result.push(educationObj);
// initialize the educationObj at the start
// and after one form finishes
educationObj = {};
}
// add entry[0] as key to the object (e.g. 'institutionName')
// with the value of entry[1] (e.g. 'Harvard')
educationObj[entry[0]] = entry[1];
counter++;
}
return result.concat(educationObj);
}
console.log(groupEducationData());
<form id="formCV" action="">
<div id="educationContainer">
<!-- First Group -->
<div class="education">
<div>
<input type="text" name="institutionName" value="Harvard">
</div>
<div>
<input type="text" name="courseName" value="Web Development">
</div>
<div>
<input type="month" name="startDate" value="2000-11">
</div>
<div>
<input type="month" name="endDate" value="2008-11">
</div>
</div>
<!-- Second Group -->
<div class="education">
<div>
<input type="text" name="institutionName" value="Oxford">
</div>
<div>
<input type="text" name="courseName" value="Business Management">
</div>
<div>
<input type="month" name="startDate" value="2009-10">
</div>
<div>
<input type="month" name="endDate" value="2010-05">
</div>
</div>
</div>
</form>
You can try FormData.getAll() and iterate over each group entry.
const institutionNames = formData.getAll('institutionName');
const courseNames = formData.getAll('courseName');
...
const educations = [];
for (let i = 0; i < institutionNames.length; i++) {
educations.push({
institutionName: institutionNames[i],
courseName: courseNames[i],
...
});
}
This is also a way to populate your desired format data.
$(document).ready(function(){
$(":button").click(function(){
var educations=$("#formCV .education");
var data=[];
educations.each(function(i,education){
var set={}
$(education).find(":input").each(function(i,value){
set[$(value).attr("name")] = $(value).val();
});
data.push(set);
})
console.log("data",data)
});
});
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<form id="formCV" action="">
<div id="educationContainer">
<!-- First Group -->
<div class="education">
<div>
<input type="text" name="institutionName">
</div>
<div>
<input type="text" name="courseName">
</div>
<div>
<input type="month" name="startDate">
</div>
<div>
<input type="month" name="endDate">
</div>
</div>
<!-- Second Group -->
<div class="education">
<div>
<input type="text" name="institutionName">
</div>
<div>
<input type="text" name="courseName">
</div>
<div>
<input type="month" name="startDate">
</div>
<div>
<input type="month" name="endDate">
</div>
</div>
</div>
<input type="button" value="click me"/>
</form>
</body>
</html>

Sum Checked CheckBoxes Values

I'm using play framework and jquery mobile and trying to sum custom tag values of checked checkboxes but i couldn't manage this. Here is some code;
<form action="#{Waiter.payAServing()}" method="POST">
<div class="boxes">
#{list items:servs, as:'serving'}
<fieldset data-role="fieldcontain">
<div class="ui-block-a">
<input onclick="MySum()" type="checkbox" name="item" id="checkbox-${serving_index}" value="${serving.id}" to="${serving.item.price*serving.amount}" />
<label for="checkbox-${serving_index}">${serving.item.title} </label>
</div>
<div class="ui-block-b"><h2><center> ${serving.item.price*serving.amount} TL </center></h2></div>
<div class="ui-block-c"><h2> ${serving.amount} </h2></div>
</fieldset>
#{/list}
</div>
<input type="hidden" name="rid" id="rid" value="${rID}" /><br />
<input type="submit" value="Pay!" />
</form>
<div class="result"></div>
<script type="text/javascript" charset="${_reponse_encoding}">
function MySum() {
alert(0);
var selectedCustomValue = document.getElementById("checkbox-1").getAttribute("to");
var sum = 0;
alert(selectedCustomValue);
}
</script>
How can i sum to values of checked check boxes with jquery or pure javascript?
Try this:
jQuery version:
function MySum(){
var totalSum = 0;
$("input:checked[name='item']").each(function(index, el){
totalSum += parseFloat(el.value);
});
return totalSum;
}
Also to bind the click handler to checkboxes use this instead on the inline style:
$(function(){
$("[name='item']").click(MySum);
});
To get the sum of to attribute, try this:
function MySum(){
var totalSum = 0;
$("input:checked[name='item']").each(function(index, el){
totalSum += parseFloat($(el).attr("to"));
});
return totalSum;
}
A better approach would be to use data-* attributes in your markup like:
<input type="checkbox"
name="item"
id="checkbox-${serving_index}"
value="${serving.id}"
data-to="${serving.item.price*serving.amount}" />
and the MySum function would be:
function MySum(){
var totalSum = 0;
$("input:checked[name='item']").each(function(a, b){
totalSum += parseFloat($(b).data("to"));
});
return totalSum;
}

Categories

Resources