I am attempting to in React JS to get the sum of a group inputs, and put the sum of their total values in a div tag.
I am trying to run this event whenever a user types in any of the inputs
The problem is I am sure React has a proper way to do this!
This is my feeble attempt (please go easy - I am new to coding :)
HTML
<input type="number" id="comp1" name="comp1" onChange={this.handleTotal} />
<input type="number" id="comp2" name="comp2" onChange={this.handleTotal} />
<input type="number" id="comp3" name="comp3" onChange={this.handleTotal} />
<input type="number" id="comp4" name="comp4" onChange={this.handleTotal} />
<input type="number" id="comp5" name="comp5" onChange={this.handleTotal} />
<input type="number" id="comp6" name="comp6" onChange={this.handleTotal} />
<div id=total></div>
JS
handleTotal = e => {
// Grab all inputs that start with ID 'comp'
let inputs = document.querySelectorAll('[id^="comp"]');
// Trying to loop through the values and get the sum of all inputs
for (var i = 0; i < inputs.length; i++) {
let totalVal = inputs[i].value
console.log(totalVal);
}
//Trying to grab total values of all inputs and put in element
document.getElementById('total').innerHTML = totalVal;
}
At the moment you are not utilizing any of the React's data binding.
Best to use React's state to hold the values of the total and all the comp inputs.
I've also used the .reduce method in order to calculate the total for each of the input fields' values. But you can achieve the same thing with a for loop.
JSFiddle: Alternative "calculateTotal" function with for loop
More information on Input handling in React
class App extends React.Component {
constructor() {
super();
this.state = {
total: 0,
numbers: {
comp1: 1,
comp2: 0,
comp3: 4,
comp4: 0,
comp5: 0,
comp6: 0
}
};
}
componentDidMount() {
// Calculates the total after component is mounted
this.setState({ total: this.calculateTotal(this.state.numbers) });
}
calculateTotal = (numbers) => {
return Object.entries(numbers).reduce((finalValue, [key, value]) => {
if (value === "") {
// if entered value is empty string "", omits it
return finalValue;
}
return finalValue + value;
}, 0);
}
handleTotal = (e) => {
const { value, name } = e.target; // gets the name and value from input field
const parsedValue = value === "" ? "" : parseFloat(value); // parses the value as a number or if empty treats it as empty string ""
this.setState((prevState) => {
// creates new immutable numbers object, using previous number values and the currently changed input value
const updatedNumbers = {
...prevState.numbers,
[name]: parsedValue
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names
};
// calculates the new total from updated numbers:
const newTotal = this.calculateTotal(updatedNumbers);
return {
numbers: updatedNumbers,
total: newTotal
}
})
}
render() {
return (
<div>
<input type="number" name="comp1" onChange={this.handleTotal} value={this.state.numbers.comp1} />
<input type="number" name="comp2" onChange={this.handleTotal} value={this.state.numbers.comp2}/>
<input type="number" name="comp3" onChange={this.handleTotal} value={this.state.numbers.comp3}/>
<input type="number" name="comp4" onChange={this.handleTotal} value={this.state.numbers.comp4}/>
<input type="number" name="comp5" onChange={this.handleTotal} value={this.state.numbers.comp5}/>
<input type="number" name="comp6" onChange={this.handleTotal} value={this.state.numbers.comp6}/>
<div id="total">{this.state.total}</div>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
You just re-assign variable in every iteration of a loop. Change to smth like this:
handleTotal = e => {
// Grab all inputs that start with ID 'comp'
let inputs = document.querySelectorAll('[id^="comp"]');
// Trying to loop through the values and get the sum of all inputs
let totalVal=0
for (var i = 0; i < inputs.length; i++) {
totalVal += inputs[i].value
console.log(totalVal);
}
//Trying to grab total values of all inputs and put in element
document.getElementById('total').innerHTML = totalVal;
}
+= operator just adds value of next element to total variable. it is equal to totalVal = totalVal + inputs[i].value
const handleFormSubmit = (e) => {
e.preventDefault();
const formData = new FormData(e.target);
let total = 0;
for (let [key, value] of formData.entries()) {
total += value * 1;
}
document.querySelector('#total').textContent = total;
};
document.addEventListener('DOMContentLoaded', () => {
const form = document.querySelector('form');
form.addEventListener('submit', handleFormSubmit, false);
});
<form>
<input type="number" id="comp1" name="comp1" />
<input type="number" id="comp2" name="comp2" />
<input type="number" id="comp3" name="comp3" />
<input type="number" id="comp4" name="comp4" />
<input type="number" id="comp5" name="comp5" />
<input type="number" id="comp6" name="comp6" />
<button type="submit">submit</button>
</form>
<span>total</span>
<div id=total></div>
Related
my code calculates the AVG or MAX of an input set of numbers, I want the user to check on a checkbox list that contains AVG and MAX for desired output but I couldn't figure out doing it.
if I put an input of "2,4" without check listing the output is both AVG and MAX which is 3 4, I tried to checklist for only AVG or MAX outcome but it didn't work.
I have checked both function calculateAVG() & calculateMAX() and they produce correct output
function proccesFloat(flt) {
var splitFloat = flt.split(",");
for (x in splitFloat) {
splitFloat[x] = parseFloat(splitFloat[x]);
}
return splitFloat;
}
function calculateAVG(setNum) {
let total = 0;
var numInput = document.getElementById("setNum").value;
var result = 0;
var avg = proccesFloat(numInput);
for (let i = 0; i < avg.length; i++) {
total += avg[i];
}
result = total / avg.length;
document.getElementById('outputAVG').innerHTML = result;
}
function calculateMAX(setNum) {
var numInput = document.getElementById("setNum").value;
var numarry = proccesFloat(numInput);
var max = 0;
for (let i = 0; i < numarry.length; i++) {
if (numarry[i] > max) {
max = numarry[i];
}
}
document.getElementById('outputMAX').innerHTML = max;
}
function calculate() {
var checkBox = document.getElementsByTagName("check");
if (checkBox[0].checked) {
calculateAVG(document.getElementById("setNum"));
}
if (checkBox[0].checked) {
calculateMAX(document.getElementById("setNum"));
} {
alert('please choose formula')
return false;
}
}
<header>
<input type="Numbers" id="setNum" placeholder="Enter Set of Numbers">
<br>
<button onclick="calculate()" id="btn1">calculate</button>
<output id="outputAVG"></output>
<output id="outputMAX"></output>
<form method="post">
<fieldset>
<legend>Formula To Calculate?</legend>
<input type="checkbox" id="avg" name="check" onclick="calculate()">AVG<br>
<input type="checkbox" id="max" name="check" onclick="calculate()">MAX<br>
<br>
</fieldset>
</form>
</header>
Count the checked and then look at the IDs.
I also suggest you wrap in a form and use the submit event
I made a few more changes to simplify the code
Let the functions do one thing and use the event to bring them together
const proccesFloat = flt => flt.split(",").map(fl => +fl); // cast to float
const calculateAVG = setNum => {
const arr = proccesFloat(setNum);
const total = arr.reduce((a, b) => a + b)
return total / arr.length;
}
const calculateMAX = setNum => Math.max(...proccesFloat(setNum));
document.getElementById("calcForm").addEventListener("submit", function(e) {
e.preventDefault(); // stop submission
const chks = document.querySelectorAll("[name=check]:checked")
if (chks.length === 0) {
alert('please choose formula')
return
}
if (document.getElementById("avg").checked) {
document.getElementById('outputAVG').innerHTML = calculateAVG(document.getElementById("setNum").value);
}
if (document.getElementById("max").checked) {
document.getElementById('outputMAX').innerHTML = calculateMAX(document.getElementById("setNum").value);
}
})
<header>
<form id="calcForm">
<input type="Numbers" id="setNum" placeholder="Enter Set of Numbers">
<br>
<button type="submit">calculate</button>
<output id="outputAVG"></output>
<output id="outputMAX"></output>
<fieldset>
<legend>Formula To Calculate?</legend>
<input type="checkbox" id="avg" name="check">AVG<br>
<input type="checkbox" id="max" name="check">MAX<br>
<br>
</fieldset>
</form>
</header>
I have three fields that are calculated: coef, cost of materials, and manufacturing cost.
First, calculate its coef * cost of materials, result in manufacturing cost input.
The calculation of the total amount is the cost of materials * manufacturing cost, but I need the ability to change the amount of Manufacturing cost and get the total result
How to do this?
My code:
function sum(el) {
let coefEl = document.getElementById('coef');
let entrPriceEl = document.getElementById('enterence_price');
let extraEl = document.getElementById('extra');
let priceEl = document.getElementById('price');
let extraresultEl;
let result;
if (el.id === "enterence_price" || el.id === "extra" || el.id === "coef") {
extraextraresultEl = parseFloat(coefEl.value) * parseFloat(entrPriceEl.value);
extraEl.value = extraextraresultEl;
result = (parseFloat(entrPriceEl.value) * parseFloat(coefEl.value) + parseFloat(extraEl.value));
if (!isNaN(result)) {
priceEl.value = result.toFixed(2);
}
} else if (el.id === "enterence_price" || el.id === "extra" || el.id === "coef") {
result = parseFloat(entrPriceEl.value) * parseFloat(extraEl.value);
if (!isNaN(result)) {
priceEl.value = result;
}
}
}
<label>Coefficient<br></label>
<input type="text" value="2" id="coef" onkeyup="sum(this);">
<br>
<label>The cost of materials<br></label>
<input type="text" value="2000" id="enterence_price" onkeyup="sum(this);">
<br>
<label>Manufacturing cost<br></label>
<input type="text" id="extra" onkeyup="sum(this);">
<br>
<label>Sum<br></label>
<input type="text" id="price" onkeyup="sum(this);">
<br>
You need to apply a different function on mf cost input, because if you will use the same function, it will never let you alter the value, because its value also getting generated from the same function you write for above 2 values
if you need something else, pls feel free to comment
let coefEl = document.getElementById('coef');
let entrPriceEl = document.getElementById('enterence_price');
let extraEl = document.getElementById('extra');
let priceEl = document.getElementById('price');
function sum(el) {
let extraresultEl;
if (el.id === "enterence_price" || el.id === "extra" || el.id === "coef") {
extraextraresultEl = parseFloat(coefEl.value) * parseFloat(entrPriceEl.value);
extraEl.value = extraextraresultEl;
result = (parseFloat(entrPriceEl.value) * parseFloat(coefEl.value) + parseFloat(extraEl.value));
if (!isNaN(result)) {
priceEl.value = result.toFixed(2);
}
} else if (el.id === "enterence_price" || el.id === "extra" || el.id === "coef") {
result = parseFloat(entrPriceEl.value) * parseFloat(extraEl.value);
if (!isNaN(result)) {
priceEl.value = result;
}
}
}
function canBeChnaged(el){
var coefVal = parseInt(coefEl.value);
var costofMatVal = parseInt(entrPriceEl.value);
var mfCostVal = parseInt(extraEl.value);
var finalSum = (coefVal * costofMatVal) + mfCostVal;
priceEl.value = finalSum.toFixed(2);
}
<label>Coefficient<br></label>
<input type="text" value="2" id="coef" onkeyup="sum(this);">
<br>
<label>The cost of materials<br></label>
<input type="text" value="2000" id="enterence_price" onkeyup="sum(this);">
<br>
<label>Manufacturing cost<br></label>
<input type="text" id="extra" onkeyup="canBeChnaged(this);">
<br>
<label>Sum<br></label>
<input type="text" id="price" onkeyup="sum(this);">
<br>
A more succinct way is to is to wrap everything into a <form> then listen for the input event. The input event will trigger a call to an event handler (in the example below it is function calc(e)) whenever the user enters data in a form control (in this case all <input>s of <form>). Use properties of HTML elements like type and step to control and validate user input. References to previously mentioned topics are located after the example below.
Details are commented in example below
// Register the <form>
const form = document.forms[0];
// Register all form controls of <form>
// In this case all <input> and <output>
const data = form.elements;
// Run function calc() if any valid user input is entered in <form>
form.oninput = calc;
// Pass the event
function calc(e) {
// Convert any valid user input of the <input>s into a real number
const c = parseFloat(data.cof.value);
const m = parseFloat(data.mat.value);
const l = parseFloat(data.lab.value);
// Reference the <output>
const s = data.sum;
// Realistic formula
const t = (c * m) + l;
// Display the value of output as the result of formula
s.value = t.toFixed(2);
}
:root,
input,
output {
font: 400 6vh/10vh Consolas;
}
label,
input,
output {
display: inline-block;
}
label {
width: 9ch;
}
input,
output {
height: 1.5ch;
width: 12ch;
text-align: right;
}
#cof {
width: 6ch;
text-align: center;
color: blue;
}
<form>
<label>Markup</label>
<input id="cof" type="number" value="2">
<br>
<label>Materials</label>
<input id='mat' type="number" value="0.00" step=".01">
<br>
<label>Labor</label>
<input id='lab' type="number" value='0.00' step=".01">
<hr>
<label>Total: </label>
<output id='sum'>0.00</output>
</form>
Reference
HTMLFormControlCollection
HTMLFormElement
<input> Element
How can I get difference between old value and the changed one?
$('input[name ="refresh"]').on("change paste keyup", function() {
???
});
So, this code (from another question) detects an input change, the input itself is number only, user set input's value from 10 to 25, how to get the difference between old and new values without pre-loading default values? By the way, default values bigger than 0.
Read the defaultValue of the element and it will have the initial value.
$('input').on("input", function() {
var defaultValue = +this.defaultValue;
var currentValue = +this.value;
console.log("defaultValue", currentValue, defaultValue, currentValue - defaultValue);
});
$('input').on("change", function() {
var lastValue = this.dataset.last || this.defaultValue;
var currentValue = +this.value;
this.dataset.last = currentValue;
console.log("last value", currentValue, lastValue, currentValue - lastValue);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="number" value="10" />
<input type="number" value="0" />
<input type="number" value="7" />
Or if you want to know what it was from the last time it was changed
$('input').on("change", function() {
var lastValue = this.dataset.last || this.defaultValue;
var currentValue = +this.value;
this.dataset.last = currentValue;
console.log("last value", currentValue, lastValue, currentValue - lastValue);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="number" value="10" />
<input type="number" value="0" />
<input type="number" value="7" />
You can store the previous value with the dataset property of the element. Just wrap your listener to access and update the appropriate properties/attributes.
const valueChangeWrapper = (e, func) => {
const
currVal = e.target.value,
prevVal = e.target.dataset.previousValue;
func(currVal, prevVal, e);
e.target.dataset.previousValue = e.target.value;
}
const changeListener = (curr, prev, e) => {
console.log(`Id: ${e.target.id}, Curr: ${curr}, Prev: ${prev}`);
};
const wrappedChangeListener = e => valueChangeWrapper(e, changeListener);
document.querySelectorAll('.listen').forEach(el => {
el.addEventListener('change', wrappedChangeListener);
el.addEventListener('paste', wrappedChangeListener);
el.addEventListener('keyup', wrappedChangeListener);
});
.as-console-wrapper { max-height: 4em !important; }
body {
display: grid;
grid-auto-flow: row;
grid-row-gap: 0.5em;
padding: 0.25em;
}
<input type="text" class="listen" id="input-1" />
<input type="text" class="listen" id="input-2" />
<input type="text" class="listen" id="input-3" />
<input type="text" class="listen" id="input-4" />
I need a user to input 2 objects in the array. If a duplicate entry is found on the number of the flight, an alert should happen. The issue is, that the alert prevents a user from entering a certain input BUT it still adds both inputs to the array even after the alert, causing the total number of miles to be wrong. The duplicate doesn't show up in the table which is good.
Upon submission of another button, the user's level is supposed to be displayed but it displays nothing. I don't know if its because of the first issue or not.
I have tried to use pop() and splice() and it produced more errors.
var total = 0;
const flightTable = document.getElementById('flightTable'),
button = document.getElementById('display'),
flightNum = document.getElementById('flightNumber'),
milesFlown = document.getElementById('milesFlown'),
addRow = () => {
const tr = document.createElement('tr'),
tdFlightNo = document.createElement('td'),
tdMilesFlown = document.createElement('td');
tdMilesFlown.setAttribute('class', 'needsToBeCounted');
/** getting the last record in the flight objects array **/
tdFlightNo.textContent = flightArray[i - 1].flightNumber;
tdMilesFlown.textContent = flightArray[i - 1].milesFlown;
/** append the TDs elements to the TR element (all of them are created above dynamically) **/
tr.append(tdFlightNo, tdMilesFlown);
/** append that row to the HTML table **/
flightTable.appendChild(tr);
}
let flightArray = [],
flightNumValue = null,
milesFlownValue = null,
i = 0;
button.addEventListener('click', () => {
flightNumValue = flightNum.value;
milesFlownValue = milesFlown.value;
/** checking for duplicate entry **/
if (flightArray.find(el => {
return el.flightNumber === flightNumValue
})) {
alert('You cannot enter this flight due to Duplicate Flight Number entry: "' + flightNumValue + '"');
return false;
}
/** add the entry in the flight objects table **/
flightArray[i++] = {
flightNumber: flightNumValue,
milesFlown: milesFlownValue
}; /** add the flight record to the array and increment the counter i (notice the i++) **/
addRow(); /** call addRow to add a new row in the table (HTML) **/
});
function getClassStatus() {
var cls = document.getElementById("flightTable").getElementsByTagName("td");
for (var i = 0; i < cls.length; i++) {
if (cls[i].className == "needsToBeCounted") {
total += isNaN(cls[i].innerHTML) ? 0 : parseInt(cls[i].innerHTML);
}
console.log(total);
//document.getElementById("classMessages").innerHTML = total +" miles";
document.getElementById("classMessages").innerHTML = "is the total amount of miles you have flown";
document.getElementById("totalNoOfMiles").value = Number(total);
console.log(total);
displayMessage();
}
function displayMessage() {
var totalValue = document.getElementsByName('totalNoOfMiles');
var bMessageTag = document.getElementById("bMessage");
var sMessageTag = document.getElementById("gMessage")
var gMessageTag = document.getElementById("sMessage");
if (totalValue < 10000) {
bMessageTag.innerHTML = "You are a Bronze member."
document.getElementById('sMessage').innerHTML = "";
document.getElementById('gMessage').innerHTML = "";
console.log(bMessageTag);
}
if (totalValue >= 10000 && total <= 24999) {
sMessageTag.innerHTML = "You are a Silver member."
document.getElementById('gMessage').innerHTML = "";
document.getElementById('sMessage').innerHTML = "";
}
if (totalValue > 25000) {
gMessageTag.innerHTML = "You are a Gold member."
document.getElementById('sMessage').innerHTML = "";
document.getElementById('bMessage').innerHTML = "";
}
}
}
<form name="attention">
<label>Please enter your flight Number:</label><br>
<input type="text" id="flightNumber" name="flightnumber" value="" />
<br />
<label>Please enter Miles Flown:</label><br>
<input type="text" id="milesFlown" name="milesflown" value="" />
<br>
<input type="button" id="display" name="display" value="Submit Flight Information" />
<br>
<input type="button" id="status" name="status" value="Get Class Level" onclick=getClassStatus(); />
<br>
<input type="number" id="totalNoOfMiles" name="totalNoOfMiles" value="" />
<div id="classMessages"></div>
<h3>Your Passenger Class Level is:</h3>
<div id="bMessage"></div>
<div id="sMessage"></div>
<div id="gMessage"></div>
<table id="flightTable">
<tr>
<th>Flight Number</th>
<th>Number of Miles</th>
</tr>
</table>
</form>
When a user enters in two inputs, the inputs should be displayed in a table after clicking a button to submit the info. For a user to get its' "level" they should click another button. Their level displays based on the sum of one of their inputs(miles). The levels should change dynamically depending on their level. A duplicate entry on flight # can not be accepted.
You total accumulator is always appending to the total so the total number of miles will forever grow.
Your messages are not displaying because values stored from type="text" inputs will always be a string where later you compare string to number. Strings are compared character by character until they are not equal or there aren't any characters left to compare. What you need is numeric comparison so number < number is a more accurate expression for your logic.
Let's get to it...
When a user adds flight information we can acquire both flight no. and miles. We want to save the miles as a numeric value as such:
milesFlownValue = Number(milesFlown.value);
Instead of declaring an iterator, you could push each object to flightArray...
flightArray.push({
flightNumber: flightNumValue,
milesFlown: milesFlownValue
});
You can then use the size of this array to a) check if the array has any elements to execute logic on and b) if so, you can execute tests using Array.prototype.some which works great for conditional statements. Notice in the below conditional that toLowerCase() is vital because you'll want flight numbers like A123 and a123 to be the same thing.
if (flightArray.length &&
flightArray.some(entry => entry.flightNumber.toLowerCase() === flightNumValue.toLowerCase()) ) {
...
}
Now when you add a new row, there's no pop() or slice() needed because you're not wanting to change the state of the original array. You can simply get the last item the traditional way...
lastItem = flightArray[flightArray.length - 1]
The rest is pretty straight forward but I've improved some code that I'm hoping you'll benefit from.
const flightTable = document.getElementById('flightTable'),
button = document.getElementById('display'),
flightNum = document.getElementById('flightNumber'),
milesFlown = document.getElementById('milesFlown'),
status = document.getElementById('status'),
classLevel = document.getElementById("classLevel");
const addRow = () => {
const tr = document.createElement('tr'),
tdFlightNo = document.createElement('td'),
tdMilesFlown = document.createElement('td'),
lastItem = flightArray[flightArray.length - 1];
tdFlightNo.textContent = lastItem.flightNumber;
tdMilesFlown.textContent = lastItem.milesFlown;
tr.append(tdFlightNo, tdMilesFlown);
flightTable.appendChild(tr);
}
let flightArray = [],
flightNumValue = null,
milesFlownValue = null,
total = 0;
button.addEventListener('click', () => {
flightNumValue = flightNum.value;
milesFlownValue = Number(milesFlown.value);
if (flightArray.length && flightArray.some(entry => entry.flightNumber.toLowerCase() === flightNumValue.toLowerCase())) {
alert('You cannot enter this flight due to Duplicate Flight Number entry: "' + flightNumValue + '"');
return false;
}
flightArray.push({
flightNumber: flightNumValue,
milesFlown: milesFlownValue
});
addRow();
});
status.addEventListener('click', () => {
total = flightArray.reduce((a, b) => a + b.milesFlown, 0)
document.getElementById("classMessages").innerHTML = `${total} is the total amount of miles you have flown`;
displayMessage();
})
function displayMessage() {
let output = "";
if (total > 0 && total < 10000) {
output = "You are a Bronze member.";
}
else if (total >= 10000 && total <= 24999) {
output = "You are a Silver member.";
}
else if (total > 25000) {
output = "You are a Gold member.";
}
classLevel.textContent = output;
}
<form name="attention">
<label>Please enter your flight Number:</label>
<br />
<input type="text" id="flightNumber" name="flightnumber" value="" />
<br />
<label>Please enter Miles Flown:</label>
<br />
<input type="text" id="milesFlown" name="milesflown" value="" />
<br />
<input type="button" id="display" name="display" value="Submit Flight Information" />
<br />
<input type="button" id="status" name="status" value="Get Class Level" />
<br />
<br />
<div id="classMessages"></div>
<div id="classLevel"></div>
<br />
<table id="flightTable">
<tr>
<th>Flight Number</th>
<th>Number of Miles</th>
</tr>
</table>
</form>
i know this has been asked before but i can't seem to get this right. I need to take input values from two text boxes and add it to another and that answer should appear in the 3rd textbox after both boxes are typed in. Nothing seems to be happening however though. Thanks
Here's the HTML
//Input 1
<input name="attribute_campaign_addon_one_time_cost_value" id="am_attribute_campaign_addon_one_time_cost_value">
//Input 2
<input name="attribute_campaign_addon_total_monthly_cost_value" id="attribute_campaign_addon_total_monthly_cost_value">
//Input 3 where added answer should go
<input name="attribute_campaign_addon_total_monthly_cost_calculated_value" id="am_attribute_campaign_addon_total_monthly_cost_calculated_value" value="">
//JQ
var $oneTimeCostField = $('#am_attribute_campaign_addon_one_time_cost_value');
var $recurringTotalCostField = $('#am_attribute_campaign_addon_total_monthly_cost_value');
var $totalRetailAmountField = $('#am_attribute_campaign_addon_total_monthly_cost_calculated_value');
function calcVal() {
var num1 = $oneTimeCostField.val();
var num2 = $recurringTotalCostField.val();
var result = parseInt(num1) + parseInt(num2);
if (!isNaN(result)) {
$totalRetailAmountField.val() = result;
}
}
calcVal();
$(num1, num2).on("keydown keyup", function() {
calcVal();
});
Your selector for the onkeyup/down is wrong, and your total field has the wrong id.
The result can be set like this: $totalRetailAmountField.val(result);
//JQ
var $oneTimeCostField = $('#am_attribute_campaign_addon_one_time_cost_value');
var $recurringTotalCostField = $('#am_attribute_campaign_addon_total_monthly_cost_value');
var $totalRetailAmountField = $('#am_attribute_campaign_addon_total_monthly_cost_calculated_value');
function calcVal() {
var num1 = $oneTimeCostField.val();
var num2 = $recurringTotalCostField.val();
var result = parseInt(num1, 10) + parseInt(num2, 10);
console.log("calcVal ", num1,num2, result);
if (!isNaN(result)) {
$totalRetailAmountField.val(result);
}
}
calcVal();
$oneTimeCostField.on("keydown keyup", function() {
calcVal();
});
$recurringTotalCostField.on("keydown keyup", function() {
calcVal();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
//Input 1
<input name="attribute_campaign_addon_one_time_cost_value" id="am_attribute_campaign_addon_one_time_cost_value">
//Input 2
<input name="attribute_campaign_addon_total_monthly_cost_value" id="am_attribute_campaign_addon_total_monthly_cost_value">
//Input 3 where added answer should go
<input name="attribute_campaign_addon_total_monthly_cost_calculated_value" id="am_attribute_campaign_addon_total_monthly_cost_calculated_value" value="">
http://api.jquery.com/val/
Jquery input value is set as follows:
$totalRetailAmountField.val(result);
First thing, I have never seen name & id such big value. this is not only cause problem in readability but also introduce error like unwanted space in id
Secondly num1 & num2 are already jquery object then what is the use of $(num1, num2)
Thirdly update the value of the third input by passing the vale as function argument $totalRetailAmountField.val(result);
var $oneTimeCostField = $('#am_attribute_campaign_addon_one_time_cost_value');
var $recurringTotalCostField = $('#attribute_campaign_addon_total_monthly_cost_value');
var $totalRetailAmountField = $('#am_attribute_campaign_addon_total_monthly_cost_calculated_value');
function calcVal() {
var num1 = $oneTimeCostField.val();
var num2 = $recurringTotalCostField.val();
var result = parseInt(num1) + parseInt(num2);
if (!isNaN(result)) {
$totalRetailAmountField.val(result);
}
}
$('#attribute_campaign_addon_total_monthly_cost_value,#am_attribute_campaign_addon_one_time_cost_value').on("keydown keyup", function() {
calcVal();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input name="attribute_campaign_addon_one_time_cost_value" id="am_attribute_campaign_addon_one_time_cost_value">
<input name="attribute_campaign_addon_total_monthly_cost_value" id="attribute_campaign_addon_total_monthly_cost_value">
<input name="attribute_campaign_addon_total_monthly_cost_calculated_value" id="am_attribute_campaign_addon_total_monthly_cost_calculated_value" value=" ">
This is a fairly verbose solution to your query.
Listen to change on each input and apply their respective values to the final answer input (input#fa)
const a1 = document.querySelector('#a1')
const a2 = document.querySelector('#a2')
const fa = document.querySelector('#fa')
const answers = []
const _handleFinalAnswer = () => (fa.value = (+answers[0] || 0) + (+answers[1] || 0))
a1.addEventListener('change', e => {
const { value } = e.target
answers[0] = value
_handleFinalAnswer()
})
a2.addEventListener('change', e => {
const { value } = e.target
answers[1] = value
_handleFinalAnswer()
})
<input type="number" step="any" name="answer 1" id="a1" />
<input type="number" step="any" name="answer 2" id="a2" />
<input name="final answer" id="fa" />
Or here is a more dynamic way to calculate all possible amount of inputs to achieve a final sum but it could still be done with two inputs :-)
const answersInputs = document.querySelectorAll('input.answer')
const finalAnswer = document.querySelector('#fa')
const _getSummedValues = () => (
[...answersInputs]
.map(input => +input.value || 0)
.reduce((prev, curr) => prev+curr, 0)
)
const _setFinal = () => finalAnswer.value = _getSummedValues()
answersInputs.forEach(input => input.addEventListener('change', _setFinal))
<input type="number" step="any" name="answer 1" class="answer" />
<input type="number" step="any" name="answer 2" class="answer" />
<input type="number" step="any" name="answer 3" class="answer" />
<input type="number" step="any" name="answer 4" class="answer" />
<input type="number" step="any" name="answer 5" class="answer" />
<input type="number" step="any" name="answer 6" class="answer" />
<input type="number" step="any" name="answer 7" class="answer" />
<input name="final answer" id="fa" />