I want to make a Calculator in JS. I'm new to JS and I don't get it why it isn't working. In the Browser Console I get undefined if I call add().
getInputAsNumber(...) should retrieves the input value from the field with the ID passed as Parameter
writeResult() writes the calculated result to the output field and is used in all operations
"use strict";
function add() {
let operator1;
let operator2;
getInputAsNumber(operator1, operator2);
let summe = operator1 operator2;
writeResult(summe);
}
function getInputAsNumber(op1, op2) {
op1 = document.getElementById("op1").value;
op2 = document.getElementById("op2").value;
}
function writeResult(result) {
let outputElement = document.getElementById("output1");
outputElement.innerHTML = Number.result;
}
<form>
<h1>Calculator with Buttons</h1>
<label>Operand 1:</label>
<input id="op1" type="number">
<br>
<br>
<label>Operand 2:</label>
<input id="op2" type="number">
<br>
<br>
<label>Operators: </label>
<button> </button>
<button>-</button>
<button>*</button>
<button>/</button>
<br>
<br>
<div id="result">
<label>Result: </label>
<output id="output1"></output>
</div>
</form>
CodePudding user response:
You are passing op1 and op2 as a referenced parameter, but they are actually called by value (which means, that they aren't changed when changing inside of the function). You get undefined because operator1 and operator2 are only declared (not initialized!).
You can modify your function so that it returns both operators (instead of passing them):
function add() {
let {operator1, operator2} = getInputAsNumber();
let summe = operator1 operator2;
writeResult(summe);
}
function getInputAsNumber() {
const op1 = document.getElementById("op1").value;
const op2 = document.getElementById("op2").value;
return {operator1: parseFloat(op1), operator2: parseFloat(op2)};
}
function writeResult(result) {
let outputElement = document.getElementById("output1");
outputElement.innerHTML = result;
}
<h1>Calculator with Buttons</h1>
<label>Operand 1:</label>
<input id="op1" type="number">
<br>
<br>
<label>Operand 2:</label>
<input id="op2" type="number">
<br>
<br>
<label>Operators: </label>
<button onClick="add()"> </button>
<button>-</button>
<button>*</button>
<button>/</button>
<br>
<br>
<div id="result">
<label>Result: </label>
<output id="output1"></output>
</div>
This function returns an object consisting of operator1 and 2 and using the object unwrapping (left side of the getInputAsNumber call) you can easily fetch the two values. Additionally: just reading the values of the input field (.value) retrieves a string (!), adding two strings in JavaScript means concatination ("2" "2" = "22"), so you need to parse them first.
CodePudding user response:
a possible code to do that...
const
myForm = document.forms['my-form']
, op =
{ add(a,b) { return a b }
, sub(a,b) { return a - b }
, mul(a,b) { return a * b }
, div(a,b) { return a / b }
};
myForm.onsubmit = e => e.preventDefault(); // disable submit
myForm.onclick = e =>
{
if (!e.target.matches('button[data-op]')) return // ignore click elsewhere
myForm.output1.textContent =
op[e.target.dataset.op]
( myForm.op1.valueAsNumber // direct access to number value
, myForm.op2.valueAsNumber // no need of parsefloat()
);
}
<form name="my-form">
<h1>Calculator with Buttons</h1>
<label>Operand 1:</label>
<input name="op1" type="number" value="0">
<br>
<br>
<label>Operand 2:</label>
<input name="op2" type="number" value="0">
<br>
<br>
<label>Operators: </label>
<button type="button" data-op="add"> </button>
<button type="button" data-op="sub">-</button>
<button type="button" data-op="mul">*</button>
<button type="button" data-op="div">/</button>
<br>
<br>
<div id="result">
<label>Result: </label>
<output name="output1"></output>
</div>
</form>
CodePudding user response:
The main issues I can see with your code is that:
- you need to either pass
op1
andop2
more directly, or [as below] set them globally so that they don't need to be passed at all - you can just use
result
, notNumber.result
[why theNumber.
in the first place?] - you might need to parse the inputs from string to number using
parseInt
Then, if you addonclick
attributes to your buttons or use enventListener, you can make the calculator work fully
"use strict";
var operator1;
var operator2;
function calcOp(operator) {
getInputAsNumber();
var op;
if (operator == 'add') {
writeResult(operator1 operator2);
} else if (operator == 'sub') {
writeResult(operator1 - operator2);
} else if (operator == 'mul') {
writeResult(operator1 * operator2);
} else if (operator == 'div') {
writeResult(operator1 / operator2);
}
}
function getInputAsNumber() {
operator1 = parseInt(document.getElementById("op1").value);
operator2 = parseInt(document.getElementById("op2").value);
}
function writeResult(result) {
let outputElement = document.getElementById("output1x");
outputElement.value = result;
}
<h1>Calculator with Buttons</h1>
<label>Operand 1:</label>
<input id="op1" type="number">
<br>
<br>
<label>Operand 2:</label>
<input id="op2" type="number">
<br>
<br>
<label>Operators: </label>
<button onclick="calcOp('add');"> </button>
<button onclick="calcOp('sub');">-</button>
<button onclick="calcOp('mul');">*</button>
<button onclick="calcOp('div');">/</button>
<br>
<br>
<div id="result"><label>Result: </label><output id="output1x"></output></div>
I changed your add
function to calcOp
because all the operations would have very similar, but if you just wanted to have add
:
function add() {
getInputAsNumber();
let summe = operator1 operator2;
writeResult(summe);
}
[Also, as one of the comments mentioned, if you wrap it as a form
the way you did, it will likely disappear after any operation. Just div
will look the same and not disappear]