Webアプリでユーザーが数値を入力し、リアルタイムで計算結果を表示したいという場面はよくあります。ショッピングカートの合計金額、消費税計算、体重・身長からのBMI計算など、様々な場面で役立つ基本テクニックです。
この記事で学べること:input値の取得方法・数値への変換・計算結果の表示・inputイベントでのリアルタイム更新・バリデーション・実践サンプル
基本実装:2つの数値を足して表示する
まずHTMLで入力フィールドと結果表示エリアを作り、JavaScriptでinputイベントを使って計算します。
<input type="number" id="num1" placeholder="数値1"> <input type="number" id="num2" placeholder="数値2"> <p>合計: <span id="result">0</span></p>
const num1 = document.getElementById("num1");
const num2 = document.getElementById("num2");
const result = document.getElementById("result");
function calculate() {
const a = parseFloat(num1.value) || 0;
const b = parseFloat(num2.value) || 0;
result.textContent = a + b;
}
// inputイベントで入力のたびに計算(リアルタイム)
num1.addEventListener("input", calculate);
num2.addEventListener("input", calculate);
ポイント:
parseFloat(value) || 0とすることで、未入力・無効な値の場合は0として計算します。整数のみの場合はparseInt()を使います。inputイベント vs changeイベント
数値入力を検知するイベントは主に2種類あります。
// inputイベント:キー入力のたびにリアルタイム発火
num1.addEventListener("input", calculate);
// changeイベント:フォーカスが外れたとき(Enter/Tab)に発火
num1.addEventListener("change", calculate);
| イベント | 発火タイミング | 向いている場面 |
|---|---|---|
| input | 文字入力のたびに発火 | リアルタイム計算・フォーム |
| change | フォーカス離脱時 | 確定後に処理・重い計算 |
実践例1:消費税計算機
<label>税抜価格: <input type="number" id="price" min="0"> 円</label> <div class="result"> <p>消費税(10%): <span id="tax">0</span>円</p> <p>税込価格: <span id="total">0</span>円</p> </div>
document.getElementById("price").addEventListener("input", function() {
const price = parseFloat(this.value) || 0;
const tax = Math.round(price * 0.1);
const total = price + tax;
document.getElementById("tax").textContent = tax.toLocaleString();
document.getElementById("total").textContent = total.toLocaleString();
});
toLocaleString():数値に桁区切りカンマを追加します(例: 1000 → “1,000”)。金額表示に使うと見やすくなります。
実践例2:BMI計算機(複数入力)
<input type="number" id="height" placeholder="身長(cm)"> <input type="number" id="weight" placeholder="体重(kg)"> <p id="bmi-result">BMI: --</p> <p id="bmi-judge"></p>
function calcBMI() {
const h = parseFloat(document.getElementById("height").value);
const w = parseFloat(document.getElementById("weight").value);
if (!h || !w || h <= 0 || w <= 0) {
document.getElementById("bmi-result").textContent = "BMI: --";
return;
}
const bmi = w / ((h / 100) ** 2);
const judge = bmi < 18.5 ? "低体重" :
bmi < 25 ? "標準" :
bmi < 30 ? "肥満1度" : "肥満2度以上";
document.getElementById("bmi-result").textContent = `BMI: ${bmi.toFixed(1)}`;
document.getElementById("bmi-judge").textContent = `判定: ${judge}`;
}
document.getElementById("height").addEventListener("input", calcBMI);
document.getElementById("weight").addEventListener("input", calcBMI);
バリデーション:不正な入力への対応
ユーザーが負の数や異常値を入力した場合のエラーハンドリングを実装します。
function validateAndCalc(input, min = 0, max = Infinity) {
const value = parseFloat(input.value);
if (isNaN(value)) {
showError(input, "数値を入力してください");
return null;
}
if (value < min || value > max) {
showError(input, `${min}〜${max}の範囲で入力してください`);
return null;
}
clearError(input);
return value;
}
function showError(input, msg) {
input.style.borderColor = "red";
// エラーメッセージ表示
let err = input.nextElementSibling;
if (!err || !err.classList.contains("error-msg")) {
err = document.createElement("span");
err.classList.add("error-msg");
err.style.color = "red";
input.after(err);
}
err.textContent = msg;
}
function clearError(input) {
input.style.borderColor = "";
const err = input.nextElementSibling;
if (err && err.classList.contains("error-msg")) err.remove();
}
よくある質問(FAQ)
Q. parseInt()とparseFloat()の違いは何ですか?
A. parseInt()は整数部分のみを取得します(例:
parseInt("3.14") → 3)。parseFloat()は小数点も含めて変換します(例:parseFloat("3.14") → 3.14)。金額や体重など小数が必要な場合はparseFloat()、個数や枚数など整数のみの場合はparseInt()を使います。Q. Number()・parseInt()・parseFloat()はどう使い分ければよいですか?
A.
Number("")は0を返し、parseInt("")はNaNを返します。空文字の扱いが異なります。Number()は厳密変換(文字混じりはNaN)、parseInt()は先頭の数値部分のみ変換("123abc"→123)という違いがあります。Q. 計算結果が小数になった場合に桁数を固定するにはどうすればよいですか?
A.
number.toFixed(2)で小数点以下2桁に固定できます(文字列が返ります)。四捨五入も自動で行われます。表示用にはparseFloat(num.toFixed(2)).toLocaleString()のように組み合わせると整数の場合に余分な.00が付きません。まとめ
input.valueは文字列なのでparseFloat()/parseInt()で数値変換が必要- inputイベントでリアルタイム計算、changeイベントでフォーカス離脱時に計算
isNaN()や範囲チェックでバリデーションを実装するtoLocaleString()で桁区切り、toFixed(n)で小数桁数を整える