Problems with Nan when getting input values

Asked

Viewed 135 times

1

I’m trying to make a calculator in Javascript/HTML, but it’s giving an error of NaN in user entries, even using a parseFloat, he still says it’s not a number, someone could tell me how to solve it?

var num1 = parseFloat(document.getElementById("n1").value);
var num2 = parseFloat(document.getElementById("n2").value);
function calculate(op) {
    var opV = document.getElementById("op");
    var operator = op.value;
    opV.value = operator;
    var res = 0;
    res = eval(num1 + operator + num2);
    var resV = document.getElementById("result");
    resV.value = res;

}
<!DOCTYPE html>
<html lang="pt_br">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Calculator</title>
    <link href="https://fonts.googleapis.com/css2?family=Lexend+Tera&display=swap" rel="stylesheet">
    <link rel="shortcut icon" href="data:image/png;base64,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" type="image/x-icon">
    <style>
        * {
            font-family: 'Lexend Tera', sans-serif;
        }
        body {
            background: white;
        }
        div#calculator {
            margin: 0;
            margin-top: 50px;
            width: 400px;
            height: 150px;
            padding: 50px;
            background-color: rgb(209, 209, 209);
            border-radius:  15px;
            margin-left: 30%;

        }
        input[name=operator] {
            width: 30px;
            height: 25px;
            text-align: center;
        }
        input[type=number] {
            width: 150px;
            height: 25px;
            border: none;
            background-color: rgb(221, 221, 221);
        }
        button[id=opr] {
            width: 175px;
            border:1px;
        }
        span {
            background-color: rgb(209, 209, 209);
            padding: 10px;
            border-radius: 50px;
            padding-left: 20px;
            padding-right: 80px;
            margin-left: 30%;
            padding-bottom: 20px;
            padding-top: 100px;
        }
        input[id=result] {
            margin-top: 10px;
            width:  350px;
            height: 30px;
        }
    </style>
</head>
<body>
    <span>
        Calculator<br>
    </span>
    <div id="calculator">
        <header>
            <input type="number" name="number1" id="n1" placeholder="Enter a number">
            <input type="text" name="operator" id="op" value=" " disabled>
            <input type="number" name="number2" id="n2" placeholder="Enter a number">
        </header>
        <main>
            <button name="+" id="opr" value="+" onclick="calculate(this)">+</button>
            <button name="-" id="opr" value="-" onclick="calculate(this)">-</button>
            <button name="x" id="opr" value="*" onclick="calculate(this)">x</button>
            <button name="/" id="opr" value="/" onclick="calculate(this)">/</button> 
        </main>

        <input type="text" id="result" disabled placeholder="Result">
    
    </div>
</body>
</html>

  • has already tried to place the two lines within the function?

  • @Leocaracciolo was worth, nor thought it could be that, it worked.

  • About the use of eval, is worth reading here and here

  • Okay thanks @hkotsubo

2 answers

2


As they say, the problem is that you carry the values of input before they are filled in, then their value is not a number, and so parseFloat returns NaN.

But contrary to what he said the other answer, I think it’s important to call parseFloat yes. Because if you click on one of the operations without filling in the numbers, the generated string will have only the symbol corresponding to the operation, giving error in eval. Even if only one of them is not filled in, it will still generate an invalid expression.

And remember to use input type="number" nay It guarantees that only numbers will be typed. Firefox, for example, allows you to type letters and any other characters, which will surely generate an invalid expression and error in eval. And Chrome, while not allowing any arbitrary text, still allows you to type things like e....eeee (since the dot is a valid character for typing numbers with decimal places, such as 2.5, and the e is used in scientific notation, such as 3.4e2 to represent the number 340, then it allows these characters even if the result is not a valid number), so if you do not call parseFloat and concatenate the strings directly, the eval will give error too.

As to the use of eval in itself, I particularly prefer not to use (see more details here and here). In case anything is typed (as in the aforementioned Firefox), the person can enter any valid command in Javascript, and this will be executed.

Of course for a simple exercise this is not a big problem, but generally speaking, you do not need the eval (may seem easy and I understand the "temptation" to use it, but if you are going to do so, you should take care to sanitize the entries to avoid further problems - read the links already indicated to learn more).

Anyway, a way to do, by checking if numbers were typed and without using eval, would be:

function calculate(op) {
    document.getElementById("op").value = op.value;
    var num1 = parseFloat(document.getElementById("n1").value);
    var num2 = parseFloat(document.getElementById("n2").value);
    if (isNaN(num1) || isNaN(num2)) {
        alert('não foram digitados os 2 números');
    } else {
        var res = document.getElementById("result");
        switch(op.value) {
            case '+':
                res.value = num1 + num2;
                break;
            case '-':
                res.value = num1 - num2;
                break;
            case '*':
                res.value = num1 * num2;
                break;
            case '/':
                res.value = num1 / num2;
                break;
        }
    }
}
<div id="calculator">
    <header>
        <input type="number" name="number1" id="n1" placeholder="Enter a number">
        <input type="text" name="operator" id="op" value=" " disabled>
        <input type="number" name="number2" id="n2" placeholder="Enter a number">
    </header>
    <main>
        <button name="+" id="opr" value="+" onclick="calculate(this)">+</button>
        <button name="-" id="opr" value="-" onclick="calculate(this)">-</button>
        <button name="x" id="opr" value="*" onclick="calculate(this)">x</button>
        <button name="/" id="opr" value="/" onclick="calculate(this)">/</button> 
    </main>

    <input type="text" id="result" disabled placeholder="Result">
</div>

I removed that lot of CSS and HTML from the original code, to make it simpler, because the important thing was to focus on Javascript and show the general idea of the code.

0

You are caching input values right when initializing the page.

var num1 = parseFloat(document.getElementById("n1").value);
var num2 = parseFloat(document.getElementById("n2").value);

Since this command runs only once when initializing, it will fetch the input values (which is a string did at that point) and parse the empty string (resulting in NaN). String type variables are values, not references, so no matter what the user types, these values will not be updated, they will always be NaN

What you should do is this:

// se for fazer caching, faça caching das referências
var num1 = document.getElementById("n1");
var num2 = document.getElementById("n2");
var resV = document.getElementById("result");
var opV = document.getElementById("op");

function calculate(op) {
    // também não há a necessidade de fazer parseFloat, se você irá
    // converter os números de volta para string
    opv.value = op.value;
    resV.value = eval(num1.value + op.value + num2.value);   
}
  • Thanks for the explanation! It worked!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.