「コーディング作業の中でフォームを作るのが苦手に感じている」
「クライアントや上司から色んな種類の入力項目を求められて毎回大変」
「ReactやVueになってから突然inputタグにvalueが登場して意味が分かっていない」
本日はそんな方に向けてフォームのコーディングを一気に解説していきます。
Webサイトやアプリにフォームを組み込む時に登場しがちな項目を紹介しますので、この記事を読んでもらえれば安心できると思います。
また動画もあるので必要に応じて使ってください。
inputタグを使ったテキスト入力の作り方
まずは一番メジャーなテキストの入力項目についてです。
氏名、電話番号、メールアドレスなど短い文章を入力してもらうときに使います。
<form action="" id="form">
<input type="text" id="inputText" value="" />
<p id="inputResult"></p>
</form>
短いテキストを入力できる欄が出来ました、横幅などはCSSで調整できますのでデザインカンプを確認するようにしましょう。
初学者向けの教材やYoutube動画では紹介されないのですが、inputタグにはvalue属性があり文字などを設定することができます。
<form action="" id="form">
<!-- valueに値を追加 -->
<input type="text" id="inputText" value="テキスト" />
<p id="inputResult"></p>
</form>
valueに設定した「テキスト」という文字が入力欄に入力されている状態で画面が表示されました。
このようにvalueに対して値を管理するのがinputタグの役割です。
実際のフォームのコーディングではvalueに値をそのまま記載することは無いのですが、valueの役割を理解していないと後々困るはずなので共有しました。
特にReactやVueなどモダンJSにも手を出す予定の方は必須の内容です。
ちなみにvalueの値はJavaScript側でも設定できます。
HTML側のvalue属性は空文字に戻しておきます。
<form action="" id="form">
<!-- valueに値を空文字に戻す -->
<input type="text" id="inputText" value="" />
<p id="inputResult"></p>
</form>
const inputText = document.querySelector("#inputText");
const inputResult = document.querySelector("#inputResult");
inputText.value = "こんにちは";
JavaScriptでも同じ名前でvalueというプロパティがあり、そちらに文字などの値を設定しておくとブラウザでは入力欄に値が入って表示されます。
またJavaScriptを使うと逆にユーザーが入力した内容を取得することができます。
const inputText = document.querySelector("#inputText");
const inputResult = document.querySelector("#inputResult");
inputText.addEventListener("change", (e) => {
const value = e.target.value;
inputResult.innerHTML = value;
});
ブラウザ上から入力欄に「田中太郎」と入力してから、カーソルを入力欄から外すと同じ値が表示されます。
ユーザーが入力した値は「e.target.value」とすれば取得できます。
今回はaddEventListenerのchangeイベントを使って、「ユーザーが入力した値を、カーソルが入力欄から外れたら欄外のpタグに出力する」ということをやってみました。
最近のフォームではこのようにユーザーが入力した内容を画面に出力する仕様がトレンドになっているので、JavaScriptを使った値の操作は覚えておきましょう。
textareaを使った長文の入力方法
inputの他にtextareaを使っても文章の入力欄を作ることができます。
inputと違ってtextareaを使うと「改行するような長文」を扱うことができます。
<form action="" id="form">
<textarea name="" id="textArea" cols="30" rows="10"></textarea>
<p id="textAreaResult"></p>
</form>
相談内容、志望動機、自由記入欄などにtextareaは使われます。
textareaもinputと同様にユーザーの入力内容を取得することができます。
const textArea = document.querySelector("#textArea");
const textAreaResult = document.querySelector("#textAreaResult");
textArea.addEventListener("change", (e) => {
const value = e.target.value;
textAreaResult.innerHTML = value;
});
ブラウザ上から長文のテキストを入力してみましょう。
inputと同様に値の取得ができてpタグに出力ができていますが、本来であれば改行も考慮したいですよね。
改行を考慮した値の取得は以下のように修正します。
const textArea = document.querySelector("#textArea");
const textAreaResult = document.querySelector("#textAreaResult");
textArea.addEventListener("change", (e) => {
const value = e.target.value;
// ここを修正
textAreaResult.innerHTML = value.split("\n").join("<br/>");
});
改行が上手く取り入れられていますね、splitとjoinという関数を使って実現しました。
split関数は引数に入れたものを起点にテキストを分割してくれるものです。
今回は「\n」としていますがプログラムの世界では「改行」を意味する記号です。
またjoin関数はバラバラになっているデータを合体させるものです。
split関数で改行を起点にテキストを分割してあったので、それぞれを合体させたわけです。
inputタグを使ってチェックボックスを作る方法
inputタグに戻りますが、inputタグではtype属性というものがありtype属性に指定した内容で色んな入力項目を作ることができます。
一例としてチェックボックスを作るには以下のようにします。
<form action="" id="form">
<label for="">
<input type="checkbox" id="checkBox" />
</label>
<p id="checkBoxResult"></p>
</form>
小さい正方形が表示されましたね、こちらクリックするとチェックを入れることができます。
inputのtype属性には「checkbox」を入れるとチェックボックスを作ってくれます。
inputをlabelで囲っている点については「項目名」を入れるためです。
<form action="" id="form">
<label for="">
<input type="checkbox" id="checkBox" />
規約の同意する
</label>
<p id="checkBoxResult"></p>
</form>
labelタグ単体というよりHTMLの全体の構成として覚えてもらう方が良いかもしれませんね。
さらにチェックボックスについてもJavaScriptで値を取得してみます。
const checkBox = document.querySelector("#checkBox");
const checkBoxResult = document.querySelector("#checkBoxResult");
checkBox.addEventListener("change", (e) => {
const value = e.target.checked;
checkBoxResult.innerHTML = value;
});
ブラウザをリロードしてチェックボックスにチェックを入れてみます。
これまでと違って「true」となりました。
同じinputでもチェックボックスについては真偽値で値を取得するようになります。
inputタグを使ってラジオボタンを作る方法
続いてラジオボタンを作っていきます。
性別や職業など、複数回答できない選択肢の項目に使われます。
<form action="" id="form">
<label for="">
<input type="radio" name="radio" value="AAA" />
AAA
</label>
<label for="">
<input type="radio" name="radio" value="BBB" />
BBB
</label>
<label for="">
<input type="radio" name="radio" value="CCC" />
CCC
</label>
<p id="inputRadioResult"></p>
</form>
チェックボックス同様にlabelでinputを囲うような構成になります。
inputタグのtype属性は「radio」を使い、value属性に選択肢と同じ値を入れておくことがポイントです。
JavaScriptでラジオボタンの値を取得する方法
ラジオボタンについてもJavaScriptで値を取得してみます。
const form = document.querySelector("#form");
const inputRadioResult = document.querySelector("#inputRadioResult");
form.addEventListener("change", (e) => {
const value = e.target.value;
inputRadioResult.innerHTML = value;
});
JavaScriptでのポイントはformタグの要素を取得することです。
これまでのテキスト入力とチェックボックスは単体なので、本体の要素を取得していれば良かったです。
ラジオボタンについては複数で構成される質問項目なので、親要素であるformタグを取得してformタグにおけるe(イベント)にアクセスする必要があるのです。
以上のように選択した値がブラウザに出力されるようになっていますね。
つまりvalue属性に入れた値が「ユーザーが選択した値をどれかを見分ける役目」になるわけです。
そのため上記のように必ずしも英語の文字列にする必要はないです、わかりやすい値を考えて入れましょう。
JavaScriptでname属性を使ったラジオボタンの値取得
ラジオボタンを使った質問項目は複数ある場合があります。
先ほどはformタグにおけるe(イベント)を使った値取得をしましたが、そもそもラジオボタンの質問項目が2つ以上になるとどちらの質問に対する答えかを見分ける必要があります。
inputタグにはname属性があり、name属性に任意の値を入れることでラジオボタンを使った質問項目が2つになっても両方を共存させることができます。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./style.css" />
<script src="./script.js" defer></script>
</head>
<body>
<form action="" id="form">
<p>プログラミング言語</p>
<label for="">
HTML
<input type="radio" name="lang" value="HTML" checked />
</label>
<label for="">
CSS
<input type="radio" name="lang" value="CSS" />
</label>
<label for="">
PHP
<input type="radio" name="lang" value="PHP" />
</label>
<p id="langResult"></p>
<hr />
<p>趣味</p>
<label for="">
料理
<input type="radio" name="hobbit" value="cook" checked />
</label>
<label for="">
キャンプ
<input type="radio" name="hobbit" value="camp" />
</label>
<label for="">
ドライブ
<input type="radio" name="hobbit" value="drive" />
</label>
<p id="hobbitResult"></p>
</form>
</body>
</html>
上記のフォームでは「プログラミング言語」「趣味」という2つの質問項目がありどちらもラジオボタンを使った回答になります。
それぞれの質問における選択肢になるinputタグにname属性を使って、プログラミング言語の選択肢か趣味の選択肢かを分けています。
ちなみにJavaScriptではname属性を使ってもHTML要素を取得することができて以下のように書きます。
const form = document.querySelector("#form");
const langResult = document.querySelector("#langResult");
const hobbitResult = document.querySelector("#hobbitResult");
form.addEventListener("change", () => {
function getRadioValue(name) {
const radios = document.getElementsByName(name);
for (const radio of radios) {
if (radio.checked) {
return radio.value;
}
}
}
langResult.textContent = getRadioValue("lang");
hobbitResult.textContent = getRadioValue("hobbit");
});
querySelectorと同じようなものでgetElementsByNameというものがあり、name属性を引数に指定することで該当するHTML要素をすべて取得できます。
ラジオボタンは複数の選択肢からできているのでfor文を使った繰り返し処理のなかでユーザーが選択した値を取得することになります。
「プログラミング言語」「趣味」のそれぞれの回答を両立させることができています。
初心者の方でたまにある勘違いとして「ラジオボタンは複数選択できる」というものがあります。
例えばHTMLを以下のように、同じ質問項目のなかで選択肢のname属性をバラバラにする方法です。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./style.css" />
<script src="./script.js" defer></script>
</head>
<body>
<form action="" id="form">
<p>プログラミング言語</p>
<label for="">
HTML
<input type="radio" name="lang1" value="HTML" checked />
</label>
<label for="">
CSS
<input type="radio" name="lang2" value="CSS" />
</label>
<label for="">
PHP
<input type="radio" name="lang3" value="PHP" />
</label>
<p id="langResult"></p>
<hr />
<p>趣味</p>
<label for="">
料理
<input type="radio" name="hobbit" value="cook" checked />
</label>
<label for="">
キャンプ
<input type="radio" name="hobbit" value="camp" />
</label>
<label for="">
ドライブ
<input type="radio" name="hobbit" value="drive" />
</label>
<p id="hobbitResult"></p>
</form>
</body>
</html>
そうすると上図のようにラジオボタンで複数選択ができました。
しかしこの方法は送信時にバグを生むことになるので使用できません。
公式ドキュメントにも明記されていて「同じ質問項目で複数の選択(checked)があると最後に選択されたものが送信される」という仕組みです。
複数選択の質問項目を作りたい場合はラジオボタン以外の方法で作るようにしてください。
ラジオボタンは単一選択のための質問項目になります。
labelタグのfor属性は何のためにあるのか?
コーディングのやり方をググったり教材を見ているとラジオボタンを使ったもので以下のような書き方を見ることがあるでしょう。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./style.css" />
<script src="./script.js" defer></script>
</head>
<body>
<form action="" id="form">
<p>住まい</p>
<label for="tokyo">東京</label>
<input id="tokyo" type="radio" name="live" value="tokyo" checked />
<label for="osaka"> 大阪 </label>
<input id="osaka" type="radio" name="live" value="osaka" />
<label for="nagoya"> 名古屋 </label>
<input id="nagoya" type="radio" name="live" value="nagoya" />
<p id="liveResult"></p>
</form>
</body>
</html>
labelタグとinputタグが入れ子になっていない書き方で、実はこの書き方でも問題ありません。
ポイントとしては選択肢それぞれについてlabelタグのfor属性とinputタグのid属性に同じ値を入れることです。
labelタグのfor属性とinputタグのid属性を同じ値にすると紐づけられるようになっています。
2つの書き方はどちらも正解なので両方知っておくと良いでしょう。
ちなみにvalue属性は「ユーザーが選択した時の値」ですので混同しないようにしましょう。
selectタグを使ってプルダウンを作る方法
ラジオボタンのように複数選択肢を設定するものにプルダウンもあります。
役割はラジオボタンと同じですが、主に都道府県や誕生日など選択肢が多いものにプルダウンは使われます。
プルダウンのHTMLでの作り方はselectタグとoptionタグを使います。
<form action="" id="form">
<select name="" id="select">
<option value="">選択してください</option>
<option value="AAA">AAA</option>
<option value="BBB">BBB</option>
<option value="CCC">CCC</option>
</select>
<p id="selectResult"></p>
</form>
selectとoptionを使うことでプルダウンを簡単に作ることができました。
クリックすると選択肢が表示されます。
selectはプルダウン全体を担う親要素になっていて、optionが選択肢になります。
selectやoptionなど見慣れないタグがありますが、構成としてはラジオボタンと同じような作りになります。
optionのvalue属性には選択肢の値を入れておくことになります。
またプルダウンの選択肢の一番目に「選択してください」など説明文を入れることもできて、その場合はvalueを空文字にしておけば大丈夫です。
それではJavaScriptで値を取得してみます。
const select = document.querySelector("#select");
const selectResult = document.querySelector("#selectResult");
select.addEventListener("change", (e) => {
const value = select.value;
selectResult.innerHTML = value;
});
プルダウンについてはselectタグの要素を取得することになります。
またoptionのvalueについては「value」とすれば取得できます。
ブラウザをリロードしてプルダウンで選択してみます。
選択肢の名前が表示されるようになりました。
加えてサイト制作やアプリ開発でよくある事例として「プルダウンの選択肢をカテゴリーごとに分けたい」という要件もあります。
主に選択肢が多い場合にユーザーの操作性を向上させることが目的です。
今回は都道府県を例にした場合、プルダウンの選択肢をカテゴリーごとに分ける場合は以下のようにします。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./style.css" />
<script src="./script.js" defer></script>
</head>
<body>
<div class="container">
<form action="">
<label for="">
<select name="" id="select">
<option value="">選択してください</option>
<optgroup label="関東">
<option value="東京">東京</option>
<option value="埼玉">埼玉</option>
<option value="千葉">千葉</option>
</optgroup>
<optgroup label="関西">
<option value="大阪">大阪</option>
<option value="京都">京都</option>
<option value="兵庫">兵庫</option>
</optgroup>
</select>
</label>
</form>
</div>
</body>
</html>
selectタグの中ではoptionタグの他にoptgroupタグというものが使えて、optgroupの中が特定のカテゴリーとしてoptionタグを扱うことになります。
またoptgroupタグのlabel属性にはカテゴリー名を指定します。
optgroupタグのlabel属性で指定したカテゴリー名は画面上ではクリックできないようになっていて、実際にクリックできるのはoptionタグで作った選択肢のみです。
ちなみに上図にあるような「選択してください」という部分はoptioinタグで作るのですが、optgroupの外に設置することになりますので注意してください。
inputタグでファイル添付を作る方法
最後にファイル添付の作り方を紹介します。
画像ファイルやPDFファイルを添付させるようなフォームはよくありますが、こちらもinputを使うと簡単に作れます。
画像データの添付と読み取り、プレビューのやり方
まずは代表的な画像データからです。
以下のようなフォームを用意します。
<form action="" id="form">
<input type="file" id="inputFile" />
<p id="inputFileResult"></p>
</form>
inputのtype属性を「file」とするとファイル添付のボタンが表示されます。
ボタンをクリックすると自分のパソコンからファイルを選択することができます。
まずは選択したファイル名をJavaScriptで取得できるようにしてみます。
const inputFile = document.querySelector("#inputFile");
const inputFileResult = document.querySelector("#inputFileResult");
inputFile.addEventListener("change", (e) => {
const value = e.target.files[0];
inputFileResult.innerHTML = value.name;
});
これまでのテキスト入力やラジオボタンと違うのが、取得される値が配列になっていることです。
さらに配列の中に選択したファイルがオブジェクトとして格納されています。
「e.target.files」をコンソールで確認してみたいと思います。
const inputFile = document.querySelector("#inputFile");
const inputFileResult = document.querySelector("#inputFileResult");
inputFile.addEventListener("change", (e) => {
console.log(e.target.files);
});
コードを上記のように変更して、ブラウザ上でファイル添付を実行してみます。
ブラウザ上でファイル添付をしてからコンソールを開いてみると以下のように表示されます。
「FileList」という配列になっていて、こちらの中身は以下のようになっています。
ファイル選択は1つしか行わないのでインデックス番号「0」のオブジェクトが格納されているのが分かります。
オブジェクトの中身は色々あるのですが、「name」というプロパティにファイル名が設定されています。
そのためコードを元に戻すのですが、「e.target.files[0]」というオブジェクトの「name」を指定するとファイル名が取得できるわけなんです。
const inputFile = document.querySelector("#inputFile");
const inputFileResult = document.querySelector("#inputFileResult");
inputFile.addEventListener("change", (e) => {
const value = e.target.files[0];
inputFileResult.innerHTML = value.name;
});
出力されるファイル名はご自身が選択されたものによって変わりますが、ファイル名を表示することができています。
ちなみに画像ファイルの場合にプレビューを表示することもできます。
画像ファイルでしか使えない方法ですが、それなりに登場するケースなので解説しておきます。
HTMLではプレビューを出力するためにimgタグを用意しておきます。
<form action="" id="form">
<input type="file" id="inputFile" />
<p id="inputFileResult"></p>
<!--ここを追加-->
<p><img id="inputFileImage" src="" alt="" /></p>
</form>
またimgタグはJavaScriptで要素の取得を行なっておきます。
const inputFile = document.querySelector("#inputFile");
const inputFileResult = document.querySelector("#inputFileResult");
// ここを追加
const inputFileImage = document.querySelector("#inputFileImage");
inputFile.addEventListener("change", (e) => {
const value = e.target.files[0];
inputFileResult.innerHTML = value.name;
});
プレビュー表示のJavaScriptの処理についてはFileReaderという組み込みオブジェクトを使います。
const inputFile = document.querySelector("#inputFile");
const inputFileResult = document.querySelector("#inputFileResult");
const inputFileImage = document.querySelector("#inputFileImage");
inputFile.addEventListener("change", (e) => {
const value = e.target.files[0];
inputFileResult.innerHTML = value.name;
// ここを追加
const reader = new FileReader();
reader.addEventListener("load", () => {
inputFileImage.src = reader.result;
});
reader.readAsDataURL(value);
});
FileReaderをインスタンス化すると自分のコード上で画像ファイルを読み込んでくれます。
またインスタンス化したFileReaderにaddEventListenerのloadイベントで、画像ファイルの読み込み結果を取得できます。
最後にreadAsDataURLという関数がありますが、こちらの引数に元のファイルオブジェクトを入れます。
inputタグをクリックして選択したファイルと、FileReaderで読み込んだファイルが同一であることを紐付ける必要があるからです。
ブラウザをリロードしてファイル選択のボタンから画像ファイルを選択すると画像が表示されるはずです。
ちなみに画像ファイルは拡張子が「png」「jpg」「jpeg」となっているファイルのことですので注意してください。
テキストデータ(.txt)の添付と読み取り、プレビューのやり方
続いてテキストデータの扱い方をやっていきます。
HTMLは以下のようになっているとします。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./style.css" />
<script src="./script.js" defer></script>
</head>
<body>
<input type="file" class="input" />
<div class="preview"></div>
</body>
</html>
テキストデータの取得では画像のときと違って文字列を認識することになるのでFileReaderのreadAsTextというメソッドを使用することで読み取りが可能になります。
const input = document.querySelector(".input");
const preview = document.querySelector(".preview");
input.addEventListener("change", () => {
const fileReader = new FileReader();
fileReader.readAsText(input.files[0]);
fileReader.addEventListener("load", () => {
console.log(fileReader);
});
});
ファイルの値については画像のときと同じでresultプロパティに入っていますね。
テキストデータをブラウザに表示したり別の変数に格納するにはresultプロパティを活用することで実現できます。
const input = document.querySelector(".input");
const preview = document.querySelector(".preview");
input.addEventListener("change", () => {
const fileReader = new FileReader();
fileReader.readAsText(input.files[0]);
fileReader.addEventListener("load", () => {
console.log(fileReader);
// ここを追加
const text = fileReader.result;
preview.textContent = text;
});
});
テキストデータ(.csv)の添付と読み取り、テーブル(表形式)でのプレビュー方法
最後にcsvデータについてやっていきます。
csvデータを聞くとエクセルデータをイメージされる方がいますが、テキストデータになりますので注意してください。
エクセルなどの表計算ソフトで扱えるだけで先ほどと同じくテキストデータです。
そのためFileReaderのreadAsTextメソッドで読み取りができます。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./style.css" />
<script src="./script.js" defer></script>
</head>
<body>
<input type="file" class="input" />
<div class="preview"></div>
</body>
</html>
const input = document.querySelector(".input");
const preview = document.querySelector(".preview");
input.addEventListener("change", () => {
const fileReader = new FileReader();
fileReader.readAsText(input.files[0]);
fileReader.addEventListener("load", () => {
console.log(fileReader);
});
});
こちらもresultプロパティに値が保存されていますね。
テキストデータではあるものの実際は表形式にして活用することが多いので、プレビューもテーブルタグでの表示にします。
まずはresultの値が文字列になっているので、こちらを1行ごとに配列にしておくことで繰り返し処理がしやすいようにします。
const input = document.querySelector(".input");
const preview = document.querySelector(".preview");
input.addEventListener("change", () => {
const fileReader = new FileReader();
fileReader.readAsText(input.files[0]);
fileReader.addEventListener("load", () => {
console.log(fileReader);
// ここを追加
let result = csv.split("\n").map((row) => {
return row.split(",");
});
console.log(result);
});
});
続いてテーブルですが今回はJavaScript側でタグを新規作成して値を入れていく方法でやっていきます。
またCSSについては以下のように書いておきました。
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
table {
width: 100%;
border-collapse: collapse;
}
td {
border: 1px solid #666;
padding: 16px;
}
tr:nth-child(1) {
background: skyblue;
font-weight: bold;
}
const input = document.querySelector(".input");
const preview = document.querySelector(".preview");
input.addEventListener("change", () => {
const fileReader = new FileReader();
fileReader.readAsText(input.files[0]);
fileReader.addEventListener("load", () => {
console.log(fileReader);
let result = csv.split("\n").map((row) => {
return row.split(",");
});
console.log(result);
// ここを追加
const table = document.createElement("table");
for (let i = 0; i < result.length - 1; i++) {
const tr = document.createElement("tr");
result[i].forEach((col) => {
const td = document.createElement("td");
td.textContent = col;
tr.appendChild(td);
});
table.appendChild(tr);
}
preview.appendChild(table);
});
});
テーブル表記を作るのは練習が必要ですので初心者の方も今のうちにやっておくことをおすすめします。
基本的には画像データ、テキストデータ、csvデータが扱えると理解が一通りできるはずですので少しずつやってみてくださいね。