Skip to Content
Course content

191: Building a Simple Calculator UI

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I've seen this happen to almost every developer the first time they build a calculator. You've got your buttons laid out, your event listeners are firing, and everything looks great—until you actually try to add two numbers. You hit 2, then +, then 3, and instead of seeing 5, your screen displays 23.

// The "Broken" Logic
let currentInput = "";
let previousInput = "";
let operator = null;

function handleNumber(num) {
    currentInput += num; // num comes from button.innerText
    updateDisplay(currentInput);
}

function handleOperator(op) {
    operator = op;
    previousInput = currentInput;
    currentInput = "";
}

function calculate() {
    if (operator === '+') {
        // BUG: "2" + "3" becomes "23"
        const result = previousInput + currentInput; 
        updateDisplay(result);
    }
}

Why your calculator is concatenating instead of adding

The issue here is that innerText and value are always strings. In JavaScript, the + operator is overworked; it handles both mathematical addition and string concatenation. When JS sees two strings, it assumes you want to glue them together, not sum them. I used to spend hours debugging this until I realized I was essentially asking the browser to join two pieces of text.

Coercing strings into actual numbers

To fix this, we need to explicitly tell JavaScript that these strings should be treated as numbers before the math happens. While you could use parseInt(), parseFloat() is the safer bet for a calculator because it allows for decimals. If you're feeling modern, the Number() constructor also works well.

function calculate() {
    // Convert strings to floats to ensure math, not concatenation
    const prev = parseFloat(previousInput);
    const current = parseFloat(currentInput);

    if (isNaN(prev) || isNaN(current)) return;

    if (operator === '+') {
        const result = prev + current;
        updateDisplay(result);
    }
    // ... other operators
}

Wiring up the buttons to the display

When building the UI, don't attach a separate event listener to every single button. That's a nightmare to maintain. Instead, use event delegation. Wrap your buttons in a container and listen for clicks at the parent level. You can then use event.target to figure out which button was pressed. It's cleaner and much more efficient.

I usually give my buttons data-attributes (like data-type="number" or data-type="operator"). This allows me to separate the visual label on the button from the logic I'm using in the script.

Managing the calculator state

A calculator is essentially a state machine. You need to track three main things: the value currently being typed, the value that was typed previously, and the operator that connects them. The trickiest part is the "transition"—what happens when the user hits an operator button? You have to move the currentInput into the previousInput slot and clear the screen for the next number, all while remembering which operation was selected. If you don't clear the current input, you'll end up appending the second number to the first one on the screen.




📋 Practical Task

Implementing a "Clear" and "Delete" Functionality

Now that you have the basic calculation logic working, your UI needs a way to recover from mistakes. Your current calculator likely lets users type numbers, but once a number is entered, there's no way to fix a typo without refreshing the page.

Your Task:

  • Add two new buttons to your HTML: one labeled "AC" (All Clear) and one labeled "DEL" (Delete).
  • Implement a function for "AC" that resets all state variables (currentInput, previousInput, and operator) back to their initial empty or null values and clears the display.
  • Implement a function for "DEL" that removes only the last character from the currentInput string using the slice() method and updates the display.
  • Ensure that if the currentInput is already empty, clicking "DEL" does nothing.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.