[JavaScript] フォーム部品の入力値を取得する(まとめ)

Webサービスを作る際に必ずと言ってよいほど利用するフォーム部品ですが、ユーザーに入力された値を取得する際にお恥ずかしながら自分でもたまにど忘れすることがあるのと、新旧の情報がごっちゃになっているため脳内の整理も兼ねてまとめておきます。

フォーム部品に値をセットしたり、選択状態をコントロールしたい場合は以下をどうぞ。 blog.katsubemakito.net

テキストボックス

getElementByIdやquerySelectorで取得したオブジェクトのvalueメソッドを参照するだけです。

<form>
  <input type="text" id="foo">
  <input type="text" name="bar">
  <button id="btn" type="button">確認する</button>
</form>

<script>
document.getElementById('btn').addEventListener('click', ()=>{
  const foo = document.getElementById('foo').value
  const bar = document.querySelector('input[type=text][name=bar]').value
  console.log(foo, bar)
})
</script>

以下のフォーム部品も同じ要領で取得できます。

  1. パスワード (<inputy type="password">)
  2. 隠しフィールド (<inputy type="hidden">)
  3. テキストエリア (<textarea>)

プルダウン(ドロップダウン)

単一

選択数が1つだけの場合はテキストボックスと同じ要領で値や順番を取得できます。

<form>
  <select id="fruits">
    <option value="apple">りんご</option>
    <option value="banana">バナナ</option>
    <option value="orange">オレンジ</option>
  </select>
  <button id="btn" type="button">確認する</button>
</form>

<script>
document.getElementById('btn').addEventListener('click', ()=>{
  const fruits = document.getElementById('fruits');
  const value = fruits.value                // 選択された値
  const index = fruits.selectedIndex        // 選択された順番
  const label = fruits.options[index].text  // 選択されたラベル

  console.log(value, index, label)
})
</script>

複数

複数同時に選択できるプルダウンの場合は少し工夫が必要です。変数fruitsには選択されたオプションの順番、値、ラベルが一つの配列になって入ります(何も選択されていない場合は空の配列)

<form>
  <select id="fruits" size="3" multiple>
    <option value="apple">りんご</option>
    <option value="banana">バナナ</option>
    <option value="orange">オレンジ</option>
  </select>
  <button id="btn" type="button">確認する</button>
</form>

<script>
document.getElementById('btn').addEventListener('click', ()=>{
  const fruits = [...document.getElementById('fruits').options]
                    .filter(o=>o.selected)                 // 選択中のoptionのみ抽出
                    .map(o=>[o.index, o.value, o.label]);  // 各optionから必要な値を取り出す
  console.log(fruits);
})
</script>

document.getElementById('fruits').optionsでプルダウン全体を取ってきていますが、これは通常の配列ではなく、HTMLOptionsCollectionが返されますので、スプレッド構文で通常の配列に戻しています。

その後filterで選択中の物だけに絞り込み、mapで必要なプロパティを取り出しています。

チェックボックス

単一

変数agreeにはboolean(trueかfalse)が入ります。

<form>
  <input type="checkbox" name="terms" id="terms" value="1"><label for="terms">利用規約に同意</label>
  <button id="btn" type="button">確認する</button>
</form>

<script>
document.getElementById('btn').addEventListener('click', ()=>{
  const agree = document.getElementById('terms').checked;
  console.log(agree);
})
</script>

複数

変数fruitsには選択されたチェックボックスvalueが通常の配列になって入ります(何も選択されていない場合は空の配列)

<form>
  <input type="checkbox" name="fruits" id="fruits1" value="apple"><label for="fruits1">りんご</label>
  <input type="checkbox" name="fruits" id="fruits2" value="banana"><label for="fruits2">バナナ</label>
  <input type="checkbox" name="fruits" id="fruits3" value="orange"><label for="fruits3">オレンジ</label>
  <button id="btn" type="button">確認する</button>
</form>

<script>
document.getElementById('btn').addEventListener('click', ()=>{
  const fruits = [...document.querySelectorAll('input[name="fruits"]:checked')].map(elm => elm.value);
  console.log(fruits);
})
</script>

document.querySelectorAll()は通常の配列ではなく、NodeListオブジェクトが返されるため、スプレッド構文で通常の配列に戻しmapでぐるぐると回しvalueだけを取り出しています。

ラジオボタン

querySelectorのセレクターに:checkedを使うことでテキストボックスと同用の方法で手軽に取得できます。ただし何も選択されていない場合はnullが返ってくるためその処理を追加する必要があります(null.valueは実行時エラーになります)

<form>
  <input type="radio" name="hardness" id="hardness1" value="1"><label for="hardness1">かため</label>
  <input type="radio" name="hardness" id="hardness2" value="2"><label for="hardness2">普通</label>
  <input type="radio" name="hardness" id="hardness3" value="3"><label for="hardness3">やわらかめ</label>
  <button id="btn" type="button">確認する</button>
</form>

<script>
document.getElementById('btn').addEventListener('click', ()=>{
  const hardness = document.querySelector('input[name="hardness"]:checked');
  const hardnessValue = (hardness === null)? null : hardness.value;
  console.log(hardnessValue);
})
</script>

ファイル

ファイルの各種情報

選択されたファイルが1つでも複数でも配列として結果が返ってくるため、1つだけを対象とする場合は単純に配列の0番目を参照します。

<form>
  <input type="file" id="avatar">
  <button id="btn" type="button">確認する</button>
</form>

<script>
document.getElementById('btn').addEventListener('click', ()=>{
  const file = document.getElementById('avatar').files[0];
  const name = file.name;   // ファイル名(例:xxxxx.jpg)
  const size = file.size;   // ファイル容量 (byte)
  const type = file.type;   // ファイルの種類 (例:image/jpeg)
  const modified = file.lastModified;  // ファイルの最終更新日時(UNIX TIME)

  console.log(name, size, type, modified);
});
</script>

file.lastModifiednew Date(file.lastModified)とすることで年月日や時間が持ってこれます。単純に書式化した日付が確認したいだけならnew Date(file.lastModified).toLocaleDateString('sv')で「2022-01-01」といった文字列が取得できます。

ファイルの中身

ローカルの画像ファイルの中身を読み込んでWebブラウザ上にそのまま表示するサンプルです。

<form>
  <input type="file" name="avatar" id="avatar">
  <button id="btn" type="button">確認する</button>
</form>

<script>
document.getElementById('btn').addEventListener('click', ()=>{
  const file = document.getElementById('avatar').files[0];
  if( ! file.type.match(/^image/) ){
    alert('画像ファイルを指定してください');
    return
  }

  const reader = new FileReader();
  reader.addEventListener('load', ()=>{
    const img = document.createElement('img');
    img.src = reader.result;
    document.body.appendChild(img);
  });
  reader.readAsDataURL(file);
});
</script>

デベロッパーツールなどで確認すればわかりますが、このサンプルを実行すると画像そののもはBASE64エンコードされ、Data URIスキームとして扱われます。

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUh(中略)JRU5ErkJggg==">

オブジェクト URL版

オブジェクト URLを利用したい場合は以下のようにします。

  const file = document.getElementById('avatar').files[0];
  const img = document.createElement('img');
  img.src = URL.createObjectURL(file);
  document.body.appendChild(img);

このときの出力結果は以下のようになります。

<img src="blob:http://example.com/4868767b-b3b9-49b0-81b7-0b717ab71160">

参考ページ